INTERNET HEATING MANAGEMENT - PART 1
-
Managing house heating through internet
The task I set myself is to remotely monitor and control the heating of my weekend home. In all cases we need internet access for remote monitoring. However, since I do not have a Wi-Fi network available at my weekend home, I used a cellular connection to access the internet.
One needs a new SIM card for an old smart phone or a tablet, which will be constantly turned on in the house and will take care of the internet connection. Enabled hotspot (GSM -> Wi-Fi) on the phone/tablet will enable the functioning of devices which are controlled through Wi-Fi modules. Such an example can be a SONOFF switch.
With off the shelf solutions there is always a missing piece that is why the system gets more and more expensive with adding functionalities and many times they do not offer needed functionalities. Homemade interface offers you the whole range of functionalities from a simple switch all the way to the so-called smart home. Of course, I am interested in the solution itself that is why I set myself a simple task for a start: Turning on and off the heater and monitoring the temperature. All other functionalities such as thermostat configuration, door opening, monitoring the alarm sensor etc. will follow suit and will be designed in the same way and using the same HW.
GUI-O app is exactly what I was looking for. I will use my old smartphone as GUI for my processor. At the same time there will also be a cellular internet connection established through the phone. Connection to my controller will be through UART/Bluetooth module and to the internet via standard cellular data transfer.
In my home workshop I have gathered all necessary components:• STM32F103CBT6 uP unit – BluePill (it can also be any other uP: Atmel, PIC, ...)
• HC06 Bluetooth module (or any other BT or BLE module)
• 5V power supply (5V Converter Board Module Power Supply Isolated AC-DC or similar)
• Relay adapter (D1 Mini Relay Module for Arduino – or similar)
• Temperature sensor (DS18S20, NTC10K – or any other temperature sensor)
• Suitable housing with a plug and a socket or a housing which is mounted on a 230V extension cord between plug and sockets.In the development phase I am additionally using ST Link V2 to programme and debugging and an UART/USB adapter for development console communication. These two units will be linked with a connector and later unplugged. After I finish developing the program the device will work independently without ST Link and UART/USB adapter.
There are many solutions on the market which offer a complex SW which we simply download to a device and it works. But when we wish to upgrade the device, we face the issue of understanding this SW. In this regard GUI-O is different. You will understand the complete code in all details and get a tool for expanding the system without any limitations. The purpose of this post is to describe the solution itself that is why I will not specifically mention or describe how I solved specific functionalities in the SW of the processor itself. I will focus on the communication only. I believe that you all are very familiar with the uP world where you can use an already developed SW to send strings and implement new functionalities in a way most convenient to you.Let’s begin – first step – setting up GUI on uP
I have connected the processors’ UART2 to the Bluetooth module (3v3, GND, Rx, Tx) and uploaded one of my apps with console communication. On uP SW I have initialized an additional UART2 port and configured it to a start speed of 9600 baud. The reception of strings from UART2 (Bluetooth module) was forwarded to an interpreter for string reception from UART1 (I have been using the UART1 as a development console for a long time). This way the SW is ready to receive responses from GUI-O. In case you do not have an interpreter, you can help yourself also with a mini SW (1).
I have uploaded a demo GUI-O app to my old phone. Until I paid for a license there was an add at the bottom of the screen. Otherwise, the app offers all functionalities. Then I connected the GUI-O app with a Bluetooth module:
• GUI-O: Menu icon on the top of the screen (three lines) or a left-to-right swipe;
• Settings -> Connections -> Default connection -> Bluetooth and IoT
• Settings -> Connections -> Bluetooth and IoT -> Available devicesWhen the GUI-O finds all Bluetooth devices we select HC06 and enter a PIN (usually 1234). The app and uP are now connected. When I press the start button in the centre of the scree in the GUI-O this will send a request for screen initialization: @init. Of course, now the app also responds with a warning: ‘Connected device not responding’, which makes sense because the response to @init request is still missing.
Since the core of my setup is turning on and off the heating, I have looked for a TG- toggle in the documentation and copied the necessary minimum data to the response string:sendstr2("|TG UID:tg1 X:50 Y:20\n\r"); /* switch with mandatory parameters */
Result: After I click on the “Start” button a working toggle appears. Image 1 shows the result before and after the toggle switch.
I have amended the parameters. On my phone the toggle is a bit too small (for my taste and my finger ) that is why I have changed the parameters and added W:25 H:5 HAW:13 HAH:13 RAD:3. I have also added a bit stronger shade SHVR:1 SHHR:1 and at the end changed the colour to FGC: #C70039 and added background transparency when toggle is off BGC:#304C4C4C. Now the toggle initialization is like this:
sendstr2("|TG UID:tg1 X:50 Y:20 W:25 H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C\r\n"); */ parameters added to the switch for a nicer design */
A more detailed description of all parameters and pre-set values can be found in the “Toggle” chapter on page 47 of the user manual (2).
To define colours an app comes in handy (3).
When you touch switch the toggle the GUI-O app responds with @tg1 1\r\n or @ tg1 0\r\n. I have upgraded the parser to accept value of a different word when receiving string @tg1 and configured the port on the uP to 1/0 for turn on/turn off the relay. This is how the basic functionality of turning on and off with GUI-O is completed.A few needed additional information
After closing the GUI-O app and then reopening it again I press the start button and a message appears saying “Bluetooth disconnected”. It is a bit inconvenient to connect the app to the Bluetooth module every time: Settings->Connections->Bluetooth and IoT -> Available devices -> HC06. That is why there is a separate Autoconnect toggle available in the settings: Settings ->Connections->Bluetooth and IoT -> autoconnect. Once activated GUI-O app connects to the Bluetooth module immediately after it is started and sends the @init message. After a restart an initialized GUI is shown and ready to operate.
On HC06 and uP SW I increased the baud rate to a more suitable speed of 115200. Then I have entered a name in HC06 which is also shown to the user when first connecting GUI-O to the HC06 module. Names of HC06 are different and if you have more than 1 in the same area at the same time the user can be confused which one is the correct one. I have entered the name: weekend_controller. More in depth instructions on how to define commands to change the speed can also be found in the Bluetooth module documentation (depends on the manufacturer).
Amending the gui-o initialization in the source code of my uPs SW requires re-upload of the amended uP SW. When booting the programme on uP I perform the complete gui-o initialization in a same way at the start of the gui-o app: @init. I do this by running the complete initialization as a subprogramme call at the end of the uP initialization but before the main() loop. For easier and faster job and in order to not need to close and open the GUI-O all the time I have added a command @cls (clears the entire screen) at the start of initialization. Otherwise GUI-O will respond with an error (element cannot be initialized twice with the same name – tg1). Now the whole initialization looks like this:sendstr2("@cls\r\n"); /* clears the entire screen */ sendstr2("|TG UID:tg1 X:50 Y:20 W:25 H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C\r\n"); */ parameters added to the switch for a nicer design */
Later, I will describe how I upgraded GUI with a display of temperature, thermostat setting, additional pictures etc. Now however, I am more interested in how GUI can be passed on through the internet to any user since this is the core of my setup.
IoT – second step – GUI on the phone (through internet)
In instructions (2) in chapter “Bluetooth with optional IoT forwarding” there is the following image that showcases the operation of IoT.
As you have already got to know the graphical elements in GUI-O are managed by uP. Through IoT a number of different users can access GUI though. In general the users can be different or have different GUI interfaces. The way how to make different GUIs for different is already predefined.
In some way separate functionality is: Setting u the communication path between phones. Communication is established via standard GUI-O MQTT server. This part is automated and you will not be dealing with it in detail but you will only turn it on and start using it.a) Working on uP with remote users:
If I add a parameter PUB:”name” during element initialization then the GUI-O app does not create a graphical element to its screen but rather forwards the string to the internet and publishes it on the MQTT server with an added name. If we wish to set up different interfaces with different remote user that we use names. The element is created only for the user, which is entered by the local user when the communication is set up. (see detailed description below: Settings -> Quick pair -> Generate QR code: and additionally optional entry of user name.) If an additional parameter is left unnamed during initialization (empty string PUB: ””), this means that we send the string to all remote users at once - to all, with and without names. The touch response of the local GUI-O screen is already known, the touch response of the remote GUI-O screen is the same, except that the usr: name parameter is added. For example, the switch returns: @ tg1 1 usr: name. When interpreting accepted strings in uP, we thus have several options. When we accept the first word @tg, we can perform further analysis of only the second word 1/0 and perform on / off the device. However, we can process the third word and recognize the switching of the remote user, and further decode which user performed the switching.
This way we can, with the use of names , initialize different GUIs for a local phone and remote users as well as different GUIs for different remote users. On the other hand we have a full control of all the users. For the beginning I will start simple, all users will have the same GUI and the same rights and the names will be empty strings.
b) Setting up a communication path between phones:
Generation of communication parameters for IoT is and automated and thus user friendly in GUI-O app. Otherwise the communication channel is established using the highest level of standard security mechanisms in order to prevent the brut force entry of a third user. MQTT is a protocol dedicated solely to communication between local GUI and remote GUI. Each local GUI generates a unique title which is assigned to the name of the device. For example: Holidayhouse_Controller. Unique title is transferred from local to remote GUI in several ways. The simplest of them is via QR code generator which generates all required data on the local phone which we then enter on to the remote phone by reading the QR code. Reading is done directly on the local phone or with the transfer of code via email or other similar communication channels.
I have downloaded GUI-O app also on my 2nd phone which is playing the role of a remote GUI. On local GUI-O we need to additionally configure:
Settings -> Connections -> IoT -> Autoconnect (when turning on GUI-O a connection to MQTT server is established)We generate required data for internet communication.
Settings -> Quick pair -> Generate QR code
GUI-O app generates required data for internet transfer and displays them on the screen in a form of a QR code. Before generating we must enter the name of the device (for example: weekend_controller) and optionally also the name of the user, which I left empty in my case. In case we are managing multiple devices with GUI-O, the app offers us a list of devices or device names to choose from when we open the app. The list is compiled by using the communication parameters for each device. Name of the device is not being used on the level of uP SW since the uP SW is tied only to one device. Entering the user name is optional. If we enter it, the parameter usr:name which is returned at the end of strings in the direction from remote GUI-O towards local GUI-O is just usr: .
Attention: After scanning the QR code from local to remote phone do not forget to confirm a successful transfer on a local phone (Press to add device). Only after you confirm this the data will be shown in the available table on a local phone.
We configure the remote GUI-O:
Settings -> Connections -> IoT -> Autoconnect
(when the GUI-O is turned on, a connection is made to the MQTT server)And scan the necessary data for internet communication.
Settings -> Quick pair -> Scan QR code
On the remote phone we read the QR code and communication channel is established.
The only thing missing now is a few pieces of code in uP. As I have described above in point a) we need to initialize GUI for remote users. I have chosen the easier way – all users will have the same screen and same rights, that is why I have added to all initialize commands PUB:”” (publish to MQTT server). This way I have also added the following in to the initializing block:
/* inicializacija oddaljenih uporabnikov */ sendstr2("@cls PUB:\”\”\r\n"); //clears the screens of all remote users sendstr2("|TG UID:tg1 X:50 Y:20 W:25 H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C PUB:\”\”\r\n"); */ the same switch also for all remote users */
After uploading the SW both phones are now working with the same toggle. Toggle on the local GUI-O is returning @tg1 1\r\n or @tg1 0\r\n to the uP while the toggle on the remote phone returns @tg1 1 usr:\r\n or @tg1 0 usr:\r\n because I have not entered the user name.
In this concrete case I can even use the same toggle name (tg1) because tg1 sent to the remote GUI-O is not being processed on a local GUI-O and the latter only shows error messages. This enables us to use the same interpreter for both toggles and execute same actions – in our case turning on and off the heating.
After receiving @tg1 we only process the second part, meaning 0 or 1.c) Miscellaneous:
You will notice though that switch of one toggle does not cause the switch in another one because the are essentially designed as independent – tow different initializations and two different responses. Programmer has to take care of the synchronization the programming way: after switching either one of the toggles to the default position we also set the relay and both toggles in the same default position since we are not analysing which toggles has executed the action or better said we do not process the presence of a third word (usr:) to change only one of two. Once the element is initialized, we can amend its parameter or status with a command: @element_ change_parameter. For elemet |TG we relay to the GUI-O the following: @tg1 EN:1\r\n or @tg1 EN:0\r\n. My code looks like this:
if (!strcmp(argument[0],"@tg1")) //adopted toggle first word analysis { if (!strcmp(argument[1],"1")) //tg1 to ON from local or remote GUI-O 2.word { HEATER_RELE_ON; // switching on the oven on port PB7 sendstr2("@tg1 EN:1\r\n"); // I set tg1 of the local GUI-O to ON sendstr2("@tg1 EN:1 PUB:\"\"\r\n"); // I set the tg1 of the remote GUI-O to ON } elseif (!strcmp(argument[1],"0")) { HEATER_RELE_OFF; // switching off the oven to port PB7 sendstr2("@tg1 EN:0\r\n"); // I set tg1 of the local GUI-O to OFF sendstr2("@tg1 EN:0 PUB:\"\"\r\n"); // I set tg1 of the remote GUI-O to OFF } }
Result: If I switch whichever toggle on the first GUI the toggle on the second GUI follows the first one. The choice which way you will go is of course yours. It is important though that if the heating is turned on by one user this is also displayed on the GUI of the second user.
d) Another operating issue:
Let’s imagine that the heater at the weekend home is on. When opening each one of the GUI-O the app will initialize the default state of the toggle to OFF (EN:0) which means that the GUI-O interface on both phones will be displaying the status as OFF but the heater will stay ON. That is why I can include a parameter EN:1 to the initialization process but this will not solve the issue. After the initialization toggles in both phones will display status ON no matter what the real state of the heater is. The only true solution to this problem is as follows: The state of the system is controlled and maintained with the data in uP. When initializing the graphic elements which display the current state we need to initialize them to the state which matches the actual operation of the system or configure them to such state after initialization with a command. I myself have taken into account the actual state during the initialization and initialized ITG with a parameter EN:1 or EN:0 depending on the state of the relay. It does not matter where in the string we put this parameter. I have added it just after the required parameters. I obtained state 1 or 0 directly from the port which controls the relay.
(((GPIOB->IDR&0x0080)>>7)&0x01) // reading port PB7 returns 1 or 0
String for my toggle initialization: |TG UID:tg1 X:50 Y:20 W:25 …. \r\n
I have broken it down to a sequential generation of three strings list item-
|TG UID:tg1 X:50 Y:20 EN: // the first part of the string
-
(((GPIOB->IDR&0x0080)>>7)&0x01) // the second part of the string 0 or 1 (depending on the state)
-
W:25 H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C\r\n // third part
What I got is a compressed code for initializing the toggle:
sendstr2("|TG UID:tg1 X:50 Y:20 W:25 EN:"); //the first part of the switch initialization sendnr2(((GPIOB->IDR&0x0080)>>7)&0x01); //number 0 or 1 (depending on the state) sendstr2(" H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C\r\n"); //Part 3
ATTENTION: Do not forget to add a space in front of the third string.
Of course, the same has to be done for the initialization on the remote phone. A complete Init block will look like this:
/* initialization of the local GUI-O */ sendstr2("@cls\r\n"); /* clears the entire screen */ sendstr2("|TG UID:tg1 X:50 Y:20 W:25 EN:"); //first part of the switch initialization sendnr2(((GPIOB->IDR&0x0080)>>7)&0x01); //number 0 or 1 (depending on the state) sendstr2(" H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C\r\n"); // Part 3 /* remote user initialization */ sendstr2("@cls PUB:\"\"\r\n"); // clears the entire screen on the remote phone sendstr2("|TG UID:tg1 X:50 Y:20 W:25 EN:"); //first part of the switch initialization sendnr2(((GPIOB->IDR&0x0080)>>7)&0x01); //number 0 or 1 (depending on the state) sendstr2(" H:5 HAW:13 HAH:13 RAD:3 SHVR:1 SHHR:1 FGC:#C70039 BGC:#304C4C4C PUB:\"\"\r\n");
Transfer of GUI to the third remote phone
Since my wife would also like to turn on or turn off the heating at the weekend house I have brosed the documentation a bit and tried to do the following: If you compare topic MQTT data of local and remote phone:
Settings -> Quick pair -> IoT devices …. first icon (down arrow)you will notice that the topic code on the local phone is the same as the topic code on the remote phone and the other way around which means that the communication can be differentiated in one way or the other. If we wish to activate a new remote user we need to copy the data of the remote user further to the new one which we can do from the remote GUI-O:
Settings -> Quick pair -> IoT devices
It contains 4 icons:- We read (or manually copy) the generated unique codes – topics for matt communication
- We display the entered data in QR form. As mentioned above this QR is different than the one on the local phone (topic in: and out: is switched). This code is intended for copying the data from a remote phone to the new user of a new remote phone. If by mistake you will scan the code from the local phone you will get a clone of the local interface which will try to communicate via matt which will result in errors caused by duplication of element names. The solution if best suited for communication through WiFi modules where remote phones are communicating directly with the uP without a local GUI-O in between. The chance for an error here is very slim or none.
- We access the communication channels to send te QR from a remote phone to and additional remote phone. There is one lack in the GUI-O here because the camera is used as scanner in GUI-O and we can not scan the photo we receive directly but we need to display it on a third screen or print it and scan it with a phone camera.
- Delete access data for a device. For example: We do not wish to continue to communicate with weekend_controller device from a specific phone.
I have now scanned the code of the 3nd icon from my remote phone to my wifes’ phone and copied all the necessary data like this. GUI-O app has immediately responded to the “Start” button. And after turning on Settings -> Connections -> IoT -> Autoconnect the interface has booted right after the GUI-O app was opened.
Now the toggle is working on all three phones without problems. One is connected locally via BT module and the other two through the internet. Now that it works everything looks very simple. I have set the basics with this and in the next posts I will describe how I designed a much nicer interface to look at.To be continued….
Sources:
-