IOT Manager Revisited

This started off as a very short blog some time ago – you’ll see  comments below but I’ve re-written it. I occasionally like to revisit stuff I have reviewed or played with ages ago because, well, things change. Had I not persevered with ImperiHome I would not now have a perfectly good IOT controller on my phone as originally it did not support Node-Red (Peter Oakes and I soon fixed that - documented elsewhere) and that package is now my preferred central control tool (the fact that it is now bog-standard fitment on the world’s most popular SBC – the Raspberry Pi – is another good reason to stick with it).

(Some regular readers may ask – what happened to BLYNK? – well,  it is still running back in the UK reliably – has been doing so for nearly 6 months – I just happen to prefer Imperihome).

IOT ManagerSo, IOT Manager is a weird one – the programming is different to many of the systems out there which try to be all things to all people – supporting endless devices many of which will no doubt bite the dust in time and it is not yet as advanced as either Blynk or Imperihome, but the author is keen – has done a LOT of changes for me and is rapidly approaching the point where it will compete with the likes of Imperihome.

http://esp8266.ru/iotmanager/

Let me say that at the time of writing you need the BETA version of IOT Manager to get the best out of it. Joinging the beta program is trivial.

So on first revisiting IOT Manager, could I HELL remember how to use it.  One of it’s original “features” was support for websockets for MQTT – fine – but it ran rather slowly and I think that’s one reason I abandoned it – so when I noted that it now also supports MQTT directly – with username and password – and figured I’d give it another shot.

So I loaded up the Android App and filled in my MQTT broker details and… nothing. Try as I might I could not figure out how to add a widget. All I had was a screen that said “no data” and a green indicator showing that it was indeed connected to my MQTT server (public address). It didn’t help that the website went on about Arduinos and stuff and really didn’t seem to get to the bottom of how to quickly get started if you didn’t have one of those. The documentation has still not quite caught up with developments.

ChartHaving loaded up IOT Manager there are no settings on the phone to create widgets  – instead, MQTT messages tell it what to do and YOU send those from, for example Node-Red! It’s really easy once you get past that hurdle.

So how the package NOW works is to initially send out a request for updates on the number and details of pages needed – and to ask for details of widgets required.

From then on the phone will request updates on specific page widgets as and when a page is selected or focus is lost. This minimises the information that needs to be sent.

When a button is pressed the info is sent back from the App by MQTT. I’ve chosen to process all of this with Node-Red. Plain NodeJS would no doubt do just as well.

Here is a list of the current widgets which includes sliders and power buttons as well as toggles…

  •       anydata
  •       simple-btn
  •       display-value
  •       small-badge
  •       power-button
  •       range
  •       toggle
  •       SteelSeries
  •       fillgauge
  •       chart

The CHART widget is new and I’ve not yet had time to test it but here’s an example on the right above.

In the example below I have three pages (named page1, page2 and page3). On the first page are two switches and a slider (range7). On the second are 3 level gauges and on page 3 are a couple of thermometer-type displays.

IOT Manager - my Node-Red code - Peter Scargill

This is what they look like…

1[4]  2[4]  3

What we have here is an APP that connects to your MQTT server (or a public one) and at that point sits and does nothing.

Essentially once the phone is connected it is listening to an MQTT subscribe. Your controller – say, Node-Red on a Raspberry Pi or even a simple ESP8266 (but you still need an MQTT broker either locally or a publically-available broker)  when it turns on and connects to the same MQTT broker, sends some init code and magically a bunch of controls appear on the phone – you can then use the controls and they send out info back to Node-Red or whatever you want to use as a central controller. What is great about this is that it could be dynamic – as this is set at the control end, not the App end.

I centralise everything via Node-Red which of course can publish and subscribe to MQTT and then control my devices from there. I decided to write the code for Node-Red to give others a starting point.

So you can see in the diagram above the two SUBSCRIBES. That info is passed to a couple of functions – here they are…

var topic=msg.topic.split("/")[3];
global.set("IoTmanager_" + topic,msg.payload);

And now the second function...

var prefix = "/IoTmanager";
var deviceId = "bedrock";
var config = [];

var pagesList = {
    pages: [
        { pageId: 10, pageName: "page1" },
        { pageId: 20, pageName: "page2" },
        { pageId: 30, pageName: "page3" }
    ]
};

var id = "0";
var widget="toggle";
  config[0] = { 
  id : id,
  page: pagesList.pages[0].pageName, 
  pageId: pagesList.pages[0].pageId,
  descr : "pump 1",
  widget : widget,
  itemstyle : "",
  itemclass : "",
  topic: prefix + "/" + deviceId + "/" + widget + id,
  color : "orange",
  style : ""
};


  id = "1";
  widget="toggle";
  config[1] = {
  id : id,
  page: pagesList.pages[0].pageName,
  pageId: pagesList.pages[0].pageId,
  descr : "pump 2",
  widget : widget,
  style1 : "",
  class1 : "",
  topic: prefix + "/" + deviceId + "/" + widget + id,
  color : "blue",
  style : ""
};

  id = "7";
  widget="range";
  config[7] = {
  id : id,
  page: pagesList.pages[0].pageName,
  pageId: pagesList.pages[0].pageId,
  descr : "range 1",
  widget : widget,
  topic: prefix + "/" + deviceId + "/" + widget + id,
  color : "blue",
  style1 : "\"style\":\"range-balanced\"",   
  badge1 : "\"badge\":\"badge-balanced\""
};


  id = "2";
  widget="fillgauge";
  config[2] = {
  id : id,
  page: pagesList.pages[1].pageName,
  pageId: pagesList.pages[1].pageId,
  widget : widget,
  class1 : "item no-border",
  style1 : "",
  descr  : "Water level",
  class2 : "light text-center",
  style2 : "font-size:24px;font-weight:bold;padding-bottom:5px;",
  topic: prefix + "/" + deviceId + "/" + widget + id,
  width  : "150",
  height : "150",
  class3 : "text-center",
  style3 : "",
  widgetConfig : {
  }
};

  id = "3";
  widget="fillgauge";
  config[3] = {
  id : id,
  page: pagesList.pages[1].pageName,
  pageId: pagesList.pages[1].pageId,
  widget : widget,
  class1 : "no-border text-center col-xs-4",
  style1 : "",
  descr  : "Fuel level",
  class2 : "assertive text-center",
  style2 : "font-size:14px;padding-bottom:5px;",
  topic: prefix + "/" + deviceId + "/" + widget + id,
  width  : "70px",
  height : "70px",
  class3 : "text-center",
  style3 : "",
  widgetConfig : {
    circleColor : "#FF7777",
    textColor : "#FF4444",
    waveTextColor : "#FFAAAA",
    waveColor : "#FFDDDD",
    circleThickness : 0.2,
    textVertPosition : 0.2,
    waveAnimateTime : 1000
  }
};

  id = "4";
  widget="fillgauge";
  config[4] = {
  id        : id,
  page: pagesList.pages[1].pageName,
  pageId: pagesList.pages[1].pageId, 
  widget    : widget,
  class1    : "no-border text-center col-xs-4",
  style1    : "",
  descr     : "Water level",
  class2    : "energized",
  style2    : "font-size:14px;padding-bottom:5px;",
  topic: prefix + "/" + deviceId + "/" + widget + id,
  width     : "70px",
  height    : "70px",
  class3    : "text-center",
  style3    : "",
  widgetConfig : {
    circleColor : "#D4AB6A",
    textColor : "#553300",
    waveTextColor : "#805615",
    waveColor : "#AA7D39",
    circleThickness : 0.1,
    circleFillGap : 0.2,
    textVertPosition : 0.8,
    waveAnimateTime : 2000,
    waveHeight : 0.3,
    waveCount : 1
  }
};

    id = "5";
    widget="steel";
    config[5] = {
    id     : id,
    page: pagesList.pages[2].pageName,
    pageId: pagesList.pages[2].pageId,
    descr  :"Steel 1",
    widget : widget,
    topic: prefix + "/" + deviceId + "/" + widget + id,
    widgetConfig : {
    width  : "auto",
    height : 100,
    type   : "Linear",
    titleString: "Thermometer 1",
    unitString : "temp C",
    threshold: 90
}
};

    id = "6";
    widget="steel";
    config[6] = {
    id     : id,
    page: pagesList.pages[2].pageName,
    pageId: pagesList.pages[2].pageId,
    descr  :"Steel 2",
    widget : widget,
    topic: prefix + "/" + deviceId + "/" + widget + id,
    widgetConfig : {
    width  : "auto",
    height : 100,
    type   : "Linear",
    titleString: "Humidity 1",
    unitString : "% Hum",
    threshold: 90
}
};


// extract command and param
var msg2 = JSON.parse(msg.payload.toString());

if (msg2.command==="getPages")
    {
     msg.topic=prefix + "/" + deviceId + "/response";
     msg.payload=JSON.stringify(pagesList);
     node.send(msg);   
    }

else if (msg2.command === "getPageById" && msg2.param > 0) 
    {
                 pagesList.pages.forEach(function(item, i, arr) {
                // it is one of our pages?
                if (item.pageId === msg2.param) {
                    // node.warn('Request is for existing page "' + item.pageName + '", pageId="' + msg2.param + '"');
                    pubPage(msg2.param);
                }
            });
    }

else if (msg2.command === "getPageById" && msg2.param === 0) 
        {
            //node.warn('Request is for All pages.');
            pubPage(0);
        }






function pubPage(page) {

    // check all widgets and pub widgets config from requested page
    config.forEach(function(item, i, arr) {
        if (item.pageId === page || page === 0) {

            // pub config for one widget
            msg.topic=prefix + "/" + deviceId + "/config";
            msg.payload=JSON.stringify(item);
            node.send(msg);
            //node.warn("Page " + item.pageId + " id " + i);
            // pub status for one widget
            pubStatus(i);
        }
    });
}


function pubStatus(i) {
var status;
switch (i)
    {
        case 0 : status=global.get("IoTmanager_toggle0"); break;
        case 1 : status=global.get("IoTmanager_toggle1"); break;
        case 2 : status=global.get("IoTmanager_fillgauge2"); break;
        case 3 : status=global.get("IoTmanager_fillgauge3"); break;
        case 4 : status=global.get("IoTmanager_fillgauge4"); break;
        case 5 : status=global.get("IoTmanager_steel5"); break;
        case 6 : status=global.get("IoTmanager_steel6"); break;
        case 7 : status=global.get("IoTmanager_range7"); break;

    }
msg.topic=config[i].topic + "/status";
msg.payload=JSON.stringify({ status: status });
node.send(msg);
}

As for individual items - well, to turn on or off a switch is as easy as...

var fred=msg.payload;
msg.topic="/IoTmanager/bedrock/toggle0/status";
msg.payload="{\"status\":\""+fred+"\"}";
global.set("IoTmanager_toggle0",fred);
return msg;

Depending on whether you fire the string "0" or "1" at that function it will turn on or off the switch.

The main function above is comprised mainly of definitions for the various items and you can find out more about them at the author's site - indeed that IS the place to look in case he changes anything and expect him to add more in future.

So - do we have an up and coming competitor for Blynk and Imperihome? I'll leave that for you to decide.

Facebooktwittergoogle_pluspinterestlinkedin

45 thoughts on “IOT Manager Revisited

  1. Hi Pete, What port did you put in the app as I'm running mosquitto on 1883, but i dont get a connection to the broker. Node red is talking mqqt ok though.

    Any thoughts.

    Regards

    Paul

    1. Hi, Paul!

      You can't use 1883 port for connecting from IoT Manager. You must add WebSockets listener to another port.
      You must add several lines to mosquitto.conf:
      listener 9001
      protocol websockets
      listener 1883
      protocol mqtt
      require_certificate false

      and connect to port 9001 from IoT Manager.
      Also see http://mosquitto.org/man/mosquitto-conf-5.html (WebSockets may be not supported in you mosquitto buld.

  2. Hi Peter,

    Marvellous, I have built a new Jessi rpi 2 and got Mosquitto & Node-Red running. I have managed to replicate your node red and it works.

    I found the "View Log" on the app very useful too.

    What I haven't mastered yet in mqqt-spy. Is there a way to show all messages not just those that you know the topic to subscribe too.

    Now to look up what else it can do.

    Cheers.

    Paul

      1. Hi Peter,

        Thanks for that simple when you know how.

        Ok. So i have now installed the IoT App on two devices, but they don't keep in sync. I can see the mqtt messages flowing. Have you tried this on two devices.

        Regards

        Paul

        1. I don't have 2 phones to test this on but I do have a tablet - as long as any action taken on a slider results in a message to Node-Red followed by the status being sent back to the phone, I see no reason why they should not stay in sync. Mine do.

  3. Ok, so I've updated the blog entry - and included my flow so far. I can test the sliders, the on-off buttons - the power button display and the badge with manual tests in Node-Red. This will run several Apps at once, keeping them in sync. All we need now is for the author to add better badges, gauges and maybe some graphing - I've also suggested small up-down button combos with text - I suggest if you find this useful that you badger the author for these - there is the basics of a really useful App here - already able to do things that others can't but it does need work so we need to encourage the author who is looking for ideas. As for the Node-Red code above- if you're familiar with Node-Red then extending this should be a breeze. If you're not familiar - now's a good time.

  4. Having problems getting this to work. Every time I change a slider or switch on the app I get
    TypeError: evalmachine.:6 node.status({fill:"blue",shape:"dot",text:"Status=" + tmp}); ^ undefined is not a function

    Anyone have any ideas why I would be getting this error on the node.status function?

    1. Comment it out for now.. I think it is because the global variable has not been defined at that point.
      The "inject at startup" should initialise everything

      context.global.light1=0;
      context.global.light2=0;
      context.global.light3=0;
      context.global.light4=0;
      context.global.light5=0;

  5. Hi Andrei
    I'd ignored node-red-contrib-ui as last time I looked it was in early stages. I've taken a look now and it has improved - but as someone looking in for the first time - it seems to be lacking the following: any kind of style, LEDs, bars, gauges. Now, that might be just me as I've realised I have no idea what a "toast" message is - I obviously need to rectify that - and also the paragraph function I'm thinking possibly lends itself to some html magic. I can find no documentation or examples of what people have done with it. What are your comments? Am I missing a huge mountain somewhere?

    1. You can use the paragraph node to create LEDs, bars and other stuff. For now it can't run any scripts that you write there.

  6. Hi. Yes this opens up another whole new world. Do you know whether there is a definitive list of the widgets with there definitions? I've seen their arduino examples but it's not obvious if they're all there.

  7. Just got the answer to my question; the latest update (1.4.7) has a pretty full description of the widgets in the Whats New section.

  8. Hi Peter

    I think there is a small problem with your current flow when you have two or more instances of the app. Your first function which is listening to control messages needs to respond with a status message. Otherwise other instances of the app will not be updated until they trigger a refresh by changing page or regaining focus. Apologies if I have missed something

    Steve

  9. Could you please post the entire flow somewhere because its a little confusing. Or maybe make a video, since that helped me with imperihomes flow :). Maybe it can help me also here :D.

    1. Hi Marko

      Well, in the case of "turn 0 off" - the first example.

      var fred=msg.payload;
      msg.topic="/IoTmanager/bedrock/toggle0/status";
      msg.payload="{\"status\":\""+fred+"\"}";
      global.set("IoTmanager_toggle0",fred);
      return msg;

  10. Hello Peter, I am Gabriel, I am beginning to learn about all this stuff just for fun. I wish to "kill two birds with the same bullet" (literal phrase from Spanish, my native language 🙂 ) making some devices to (startrek home, holodeck discarded 🙂 )
    Your article was very helpful and it works like a charm at my first chance!
    I was looking for something to reduce code lines on my ESP8266 when using IoTmanager (to let space to add OTA, battery control, anti fault and error management, etc.) and I guess you get the point!
    May be I am very ambitious but I am trying to link your idea with ESPMetRED library, so far so good I made work that library too, based on the examples. But not both on the same project! (just a couple of gauges telling data read from a DHT22). Even I integrated your node-red example and manually can control GPIO, but... (I just would be happy to get a guide or an example to get a led brightening on my ESP8266 after sliding a toggle control on IoTmanager using your node-red idea) (Sorry for the extension but You deserve a little introduction and presentation)

    1. Good afternoon Gabriel - in the UK we say "kill two birds with one stone" - I guess when the phrase was invented we didn't have bullets. Sorry but while interesting I'm not entirely sure what the question is.... I took a look at the ESPMETRED library - and that's not making much sense either. My own code on the ESPs basically does everything that is too integral to do remotely - ie control displays, I2c etc and all comms is done by MQTT - but I don't use the Arduino stuff- I use the Espressif library and C code along with TUANPMs MQTT library to talk back to Node-Red.

      1. Thank you Peter for your fast replay, and yes, I was wrong, the word is "rock" not "bullets". Sorry about my English, my native language is Spanish and sometimes I could be confuse.
        About on what to use to program the ESP I guess it is not Important here when all the communication is by MQTT, I mean, you can take the ESP like a black box(BB). Some MQTT come in, BB react to that and do something and/or bring back another MQTT. Even not need to be an ESP.
        What I can´t make it work is when you toggle to "on" the IoTmanager control and get an MQTT message from it. I can do it manually like as on your example, but not from the inner control on iotmanager screen. (In the other reply I added a little (and messy) RED layout about my tests).

  11. Your example Works like a charm!, even I could receive data from my esp8266 using ESPMetRED and DHT22 on fillgauges. But I can´t light a led on GPIO with iotmanager toggle widget example. Could you guide me on that please? (I am a newbie, please have mersy with technical explanation, I am a "while v==work; copy; paste; try; googlesearch; return" student :-))

    1. I guess I need another MQTT input to get the value ("ON"/"OFF") from IoTmanager to replace injection on "switch" or "pump2". But I can´t discover to what topic (I tested with "status" value of that device, but didn´t work)

Leave a Reply to Alan Cancel reply

Your email address will not be published. Required fields are marked *