Accessing a Single Device from Multiple Blynk Projects?

distribute = share so that everyone can use the same device together

I’m not a business, I just want some users in the house to have less feature access to the same device hence different apps.

I can see the business value if you want to distribute 100’s of devices and not have to pay to clone the apps and perhaps aggregate lots of hardware data in one place for a web dashboard but again that is not what I need here

Like what?

lights control for example …

your app has control of all the lights so you can see and turn them on/off as required but the kids app is limited to their room and common areas

timers …
you app can set and control timers but the kids cant

The existing fix for widgets like buttons and sliders is with Terminal and a timeout.

So any widget you want to restrict access to requests your master PIN via Terminal, if it’s not entered after X seconds the widget request is ignored.

I don’t use sharing but I believe the Timer widget is not available to shared users. Do you mean the Time Input widget?

tapping in a pin every time i start an app to unlock features is not very user friendly and the target is having to parse that and get involved by sending back vpin widget changes? also all those widgets are visible even if they may not be active ? and non-expert users don’t want to see a terminal that is just plain ugly they want to see nice buttons and sliders simple controls only

yeah time input widget, the ESP would do the time compare and turn on at correct time not asking the app or blynk library to do any timer services as Ive already got NTP and local time correction on the target

If your household is that fussy then I think they need Blynk’s bespoke service.

come on … that is not fussy that is design for purpose
a terminal is a bit ‘technical’ to be putting on the screen of a simple users app but perfectly fine for me as the designer/expert user of the devices

but the simple users will never see the terminal because it will be off screen on a tab that they never use i.e. they don’t use the pin system.

but if the tab is there they can navigate and look at it, even try entering things …

and nothing will happen because they don’t have the PIN.

I really appreciate that you are giving me some good technical answers to this problem, thank you

but it really is not nice to have disabled widgets and terminals in a ‘simple user’ app even when on other tabs, it is just not clean design.

I’ll use some of your suggestions for now but the original topic question still stands …

I’d like to be able to write a small group of different blynk apps with slightly different purpose talking to a single hardware instance

If in the end it means a business license would be needed for this hinted at feature multitenancy? (not made clear what that is and no clue searching your site) that is no good for a home user like myself

thank you again

Thanks to everyone who replied to this topic. I’ve learned a few things and have a few things to study more. I’ll summarize my general thoughts here and then post a corresponding topic in the “Ideas” area.

After reviewing many other topic threads on related issues, it seems there is a significant need from the Blynk community for the topic subject. Granted, it may be in development for business users, but I personally think it would serve hobbyists as well as business users if this capability were more directly supported at all levels. Let’s face it, business adoption usually stems from individual user adoption. While it appears there are potential work-arounds to support multiproject-to-single-device capabilities, the current state of the system does not lend itself well to most casual end-users that need to see data across devices.

I’ll also share another way to think about this capability from a higher level. I think the Blynk infrastructure would benefit immensely from a capability to create projects with different “VIEWS” into the underlying hardware. Doing so would open up huge application possibilities that could benefit the techie-nerd like myself all the way to the non-technical end user that is pointed to a friendly mobile app that they just use without any understanding of the underlying architecture.

Finally, I understand that technology evolves gradually and Blynk is no exception. I personally think that Blynk is a truly awesome platform that helps IoT developers like myself move from idea to working app with incredible speed. Thanks to all of you who work so tirelessly on the Blynk project.

Just my two cents for what it’s worth.

There apparently is a text input widget on the development table…

There isn’t… I said it, and widget lockout, it was a feature that has been requested… whether it is to be done or not is up to the developers…

Meanwhile something like it can be implemented (well the widget lockout part) via code and PIN or touch pattern codes, etc… As with most everything technical with these MCUs, your imagination and coding skills determine the results.

Something like this will email you when the pesky kids try to change the Time Input settings and lock them out of button and slider use.

// EziSchedV5.ino (

#define BLYNK_PRINT Serial 
#include <ArduinoOTA.h>             
#include <ESP8266WiFi.h>        
#include <BlynkSimpleEsp8266.h> 
BlynkTimer timer;

#include <TimeLib.h>
#include <WidgetRTC.h>
WidgetRTC rtc;
char currentTime[9]; 
const int relayPin = 5;  // WeMos D1
int relayState = HIGH;   //  OFF for active HIGH relays
unsigned int trigger = 1; 
String terminalString;     // for entering the PIN
String validPIN = "1965";  // set your PIN number here
long lastPINtime;
long PINtimeout = 10000L;  // default, after 10s valid PIN will be cleared but changeable with slider
bool triedPIN = false;   
bool rebooted = true;  // this bool overwrites PIN request on initial server connection for sync to work
long originalschOnestartseconds;
long originalschOnestopseconds;
long originalschTwostartseconds;
long originalschTwostopseconds;
bool TimeInputsyncSched1 = false;
bool TimeInputsyncSched2 = false;
bool sliderSync = false;

char auth[] = "xxx";
char ssid[] = "GoldenAP";
char pass[] = "xxx";
char server[] = "blynk-cloud.com";

bool clockSync = false;
char myhostname[] = "EziSchedV5";  // for OTA and router identification    

void setup() {
  WiFi.hostname(myhostname);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, relayState);
  Serial.begin(115200);
  Serial.println("\nRebooted");
  Blynk.begin(auth, ssid, pass, server);
  ArduinoOTA.setHostname("myhostname");       
  ArduinoOTA.begin();    
  timer.setInterval(1000L, clockDisplay);  // check every second if time has been obtained from the server
                                       // and if ON / OFF trigger time has been reached
}

BLYNK_CONNECTED() {
  rtc.begin();
  Blynk.virtualWrite(V4, "\n\n\n\n\nRebooted\n\n");
  Blynk.syncVirtual(V3);  // ensure relay, virtual button and virtual LED are as they were before reboot
  Blynk.syncVirtual(V5);  // get PIN timeout from server
}

void activetoday(){         // check if schedule #1 should run today
  if(year() != 1970){
    Blynk.syncVirtual(V1);  // sync scheduler #1 
    Blynk.syncVirtual(V2);  // sync scheduler #2  
  }
}

void clockDisplay(){  // only needs to be done once after time sync
  if((year() != 1970) && (clockSync == false)){ 
    sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
    Serial.println(currentTime);
    clockSync = true;
  } 
  if ((millis()  >  lastPINtime + PINtimeout) && (triedPIN == true)){  
    Blynk.virtualWrite(V4, "Pin timeout\n\n");
    terminalString = "";
    triedPIN = false;
  }
  activetoday();
} 

// V0 LED

BLYNK_WRITE(V1) {   // Scheduler #1 Time Input widget  
  TimeInputParam t(param);
  unsigned int nowseconds = ((hour() * 3600) + (minute() * 60) + second());
  unsigned int startseconds = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);  
  unsigned int stopseconds = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
  if (TimeInputsyncSched1 == true){
    if((startseconds != originalschOnestartseconds) || (stopseconds != originalschOnestopseconds)){
      originalschOnestartseconds =  startseconds;
      originalschOnestopseconds =  stopseconds;
      Blynk.email("Scheduler", "Someone changed schedule 1 ON / OFF time");
      Serial.println("Someone changed schedule 1 ON / OFF time");
      Blynk.virtualWrite(V4, "SCH1 ON / OFF time updated\n\n");
    } 
  }
  else{
    TimeInputsyncSched1 = true;
    originalschOnestartseconds =  startseconds;  
    originalschOnestopseconds =  stopseconds;
  }
  int dayadjustment = -1;  
  if(weekday() == 1){
    dayadjustment = 6; // needed for Sunday Time library is day 1 and Blynk is day 7
  }
  if(t.isWeekdaySelected((weekday() + dayadjustment))){ //Time library starts week on Sunday, Blynk on Monday  
    //Schedule is ACTIVE today 
    if(nowseconds > startseconds && nowseconds <= startseconds + trigger ){    // ON trigger command is sent
      Serial.println("Schedule 1 started");
      terminalString = validPIN;   // disable PIN validation
      Blynk.virtualWrite(V3, 1);
      Blynk.syncVirtual(V3);
      Blynk.virtualWrite(V4, "Schedule 1 started\n\n");    
      lastPINtime = millis();      // enable PIN validation
      triedPIN = true;
    }                  
    if(nowseconds > stopseconds && nowseconds <= stopseconds + trigger ){   // OFFtrigger command is sent
      Serial.println("Schedule 1 finished");
      terminalString = validPIN;   // disable PIN validation      
      Blynk.virtualWrite(V3, 0);
      Blynk.syncVirtual(V3);
      Blynk.virtualWrite(V4, "Schedule 1 finished\n\n");     
      lastPINtime = millis();      // enable PIN validation
      triedPIN = true;
    }              
  }
}

BLYNK_WRITE(V2) {   // Scheduler #2 Time Input widget  
  TimeInputParam t(param);
  unsigned int nowseconds = ((hour() * 3600) + (minute() * 60) + second());
  unsigned int startseconds = (t.getStartHour() * 3600) + (t.getStartMinute() * 60);  
  unsigned int stopseconds = (t.getStopHour() * 3600) + (t.getStopMinute() * 60);
  if (TimeInputsyncSched2 == true){
    if((startseconds != originalschTwostartseconds) || (stopseconds != originalschTwostopseconds)){
      originalschTwostartseconds =  startseconds;
      originalschTwostopseconds =  stopseconds;
      Blynk.email("Scheduler", "Someone changed schedule 2 ON / OFF time");
      Serial.println("Someone changed schedule 2 ON / OFF time");
      Blynk.virtualWrite(V4, "SCH2 ON / OFF time updated\n\n");
    }   
  }
  else{
    TimeInputsyncSched2 = true;
    originalschTwostartseconds =  startseconds;  
    originalschTwostopseconds =  stopseconds;
  }
  
  int dayadjustment = -1;  
  if(weekday() == 1){
    dayadjustment = 6; // needed for Sunday Time library is day 1 and Blynk is day 7
  }
  if(t.isWeekdaySelected((weekday() + dayadjustment))){ //Time library starts week on Sunday, Blynk on Monday  
    //Schedule is ACTIVE today 
    if(nowseconds > startseconds && nowseconds <= startseconds + trigger ){    // ON trigger command is sent
      Serial.println("Schedule 2 started");
      terminalString = validPIN;   // disable PIN validation
      Blynk.virtualWrite(V3, 1);
      Blynk.syncVirtual(V3);  
      Blynk.virtualWrite(V4, "Schedule 2 started\n\n");         
      lastPINtime = millis();      // enable PIN validation  
      triedPIN = true;      
    }                  
    if(nowseconds > stopseconds && nowseconds <= stopseconds + trigger ){   // OFF trigger command is sent
      Serial.println("Schedule 2 finished");
      terminalString = validPIN;   // disable PIN validation
      Blynk.virtualWrite(V3, 0);
      Blynk.syncVirtual(V3);
      Blynk.virtualWrite(V4, "Schedule 2 finished\n\n");     
      lastPINtime = millis();      // enable PIN validation 
      triedPIN = true;
    }                  
  }
}

BLYNK_WRITE(V3){   // button for active HIGH relay, SWITCH mode
  if ((terminalString == validPIN) || (rebooted == true)){
    if(param.asInt()){
      relayState = HIGH; 
    }
    else{
      relayState = LOW;
      
    }
    Blynk.virtualWrite(V0, relayState * 255);   // turn OFF virtual LED ON / OFF
    digitalWrite(relayPin, relayState);
    Serial.print("Relay state: ");
    Serial.println(relayState);
  }
  else{
    Blynk.virtualWrite(V4, "[" + String(millis()) + "]  Enter PIN\n\n");
  }
  rebooted = false;
}

BLYNK_WRITE(V4){                     // Terminal widget
  terminalString = param.asString();
  if(terminalString == validPIN){
    Blynk.virtualWrite(V4, "Widgets unlocked\n\n");
    triedPIN = true; 
    lastPINtime = millis();    
  }
  else{
    Blynk.virtualWrite(V4, "Invalid Pin\n\n");    
  }
}

BLYNK_WRITE(V5){                        // slider for PIN timeout
  if ((terminalString == validPIN) || (sliderSync == false)){
  PINtimeout = param.asInt() * 1000;   // set new timeout
    Blynk.virtualWrite(V4, String(PINtimeout / 1000) + "s PIN timeout\n\n");   
    Serial.println(String(PINtimeout / 1000) + "s PIN timeout");
  }
  else{
    Blynk.virtualWrite(V4, "[" + String(millis()) + "]  Enter PIN\n\n");
  }  
  sliderSync = true;
}

void loop() {
  if(Blynk.connected()){ 
    Blynk.run();        
  }                     
  ArduinoOTA.handle(); 
  timer.run();
}
1 Like