RF433Mhz Transceiver
Table of Contents
Introduction
The 433Mhz transmitter (FS1000A) and receiver (MX-RM-5V) modules are widely available online. The source code below used on the PICO to decode and transmit 433 Mhz signals originates from : pico433mhz/src at main · AdrianCX/pico433mhz · GitHub 2 with more info at
The transmitter module is powered by the Pico's 5v output from VBUS. No additional antennas were used, but successfully transmits through exterior/interior walls without issue.
Sniffing/Sending RF key codes
Start the receiver with an HTTP call to the Pico's ip address. Open a command prompt in Windows and enter:
curl -v "http://[ip-address]:80/receive"
after getting "200 OK" bring the RF Remote very close to the RF receiver module attached to the PICO and press the remote button to be sniffed a few times. After 15 seconds the it will return the key details.
To send the key code enter:
curl -v "http://[ip-address]:80/send/[code]/[protocol]/[pulselength]"
Preliminary Node Red Design
The UI to the PICO was through a Raspberry pi running Node Red.The preliminary design utilized ui-switches, typically limited to on or off states, for controlling the RF plugs. Unfortunately, there was no indication in the user interface (UI) regarding the success of the HTTP request to the PICO. However, this issue was resolved in the subsequent iteration of the Flow by incorporating template nodes and CSS classes, enabling the addition of extra appearance states to the ui-switch icons.
Node Red
Additional Nodes used: node-red-contrib-arp
PICO mac address assigned to an Environmental Variable
The mac address is a device's fundamental physical address whereas its ip address on a network is not fixed, but it can be determined from its mac address.
The fixed mac address of the PICO is therefore stored as a Constant by assigning it to to a Group Environmental variable RFmac during Flow creation.
Automatic finding of the PICO ip
At boot-up the environmental variable RFmac is set to a Flow context scope in Set Flow RFmac Function node.
if (flow.get("RFmac")===undefined){
flow.set("RFmac",env.get("RFmac"))}
return msg;
To automate the retrieval of the PICO IP address from the ARP node, the PICO MAC address needs to be provided as msg.payload.macs input. The Function node Set msg.payload.macs adds the object macs to the payload by first adding an empty object to the msg.payload with JSON {} then uses a second rule to add and set msg.payload.macs to the value of flow.RFmac. The msg.payload output from the ARP node is an array of objects containing :
ip : the IP address of the device.
mac : the MAC address of the device.
iface : the network interface of the device.
The IP address is extracted from an array by accessing the "ip" object within the array in the ARP node's msg.payload. The extracted IP address is then stored in flow.PICOip by assigning it the value msg.payload[0].ip in the Set flow.PICOip Change node.
To test the PICO connection with an inappropriate IP, you can use the "TEST corrupt PICOip connection" feature. This allows you to set an invalid IP address for the PICO for testing purposes.
If the RF HTTP Request fails to find the PICO's IP address because it has changed on the network, the Catch node (RF HTTP Request Error) is triggered. In such cases, the system automatically initiates the process of finding the IP address from the PICO's MAC address.
The UI
The Main Flow
Flow Description
This flow controls a group of RF (radio frequency) plugs using a user interface. Here's an overview of its logic:
1. The program starts with a group node that contains multiple nodes related to controlling RF plugs.
2. Each RF plug is represented by a "ui_switch" node, which provides a switch interface to turn the plug on or off.
3. The "ui_switch" nodes are connected to an "http request" node, which sends an HTTP GET request to control the RF plugs, and to the "function" node Set State which sets the "ui-switch" appearance states. However these instructions are blocked by the "switch" node Stateless if the msg.StatusCode has already been set. This ensures that following an http request the feedback to the switch only affects the "ui-switch" change of state and does not propagate repeated http-requests.
4. There is also a "Kill Switch" represented by another "ui_switch" node, which, when turned on, stops the flow of messages and disables the other switches.
5. When the "Kill Switch" is turned on, a "change" node called "Disable Switches" sets the `enabled` property of the messages to `false`, effectively disabling the switches.
6. If the "Kill Switch" is turned off, a "switch" node called "Enable Switches" checks the type of the payload received. If it is a number, it means the switch is enabled, and the `enabled` property is set to `true`.
7. The "Enable Switches" node is connected to a "delay" node called "Switch off all," which introduces a delay of 50 milliseconds before proceeding.
8. After the delay, the messages from the "Switch off all" node are sent to an "http request" node to control the RF plugs.
9. The responses from the "http request" node are then passed to a "function" node called "Set State," which keeps track of the state of each switch and stores it in the flow context. [See Setting the State]
10. The "Set State" function node also responds with the current state and the `enabled` property when a "get state" message is received.
11. The state information is used to control the appearance of the switches in a user interface by modifying the CSS classes of the corresponding "ui_switch" nodes.
The appearance of the switches is controlled by the change and template nodes when a HTTP GET request is made and whether it is successful or not.
When a HTTP GET request is made:
The change node labeled "Requesting" sets the className property of the message to "REQ" and the statusCode property to "Request". This indicates that a request is being made and updates the status of the switch accordingly.
When the HTTP GET request is successful:
The http request node sends the request to the specified URL.
If the request is successful (status code 200), the http request node outputs a message with the statusCode property set to 200.
The change node labeled "Index, plugCode to payload" then sets the className property of the message to "SUCCESS" and moves the plugCode property to the payload.
The message with the updated className property is then passed to the template node.
When the HTTP GET request is not successful:
If the request encounters an error (e.g., status code is not 200), the http request node outputs a message with the statusCode property set to the corresponding error code.
The change node labeled "Index, plugCode to payload" sets the className property of the message to "FAIL".
The message with the updated className property is then passed to the template node.
In the template node labeled "Auto Set flow.RFmac from Group env", the CSS styles defined in the template are applied based on the className property of the message. The UI switches associated with the corresponding Node IDs and their respective states are styled accordingly. For example, the SUCCESS class sets the switches to black when they are in the "on" state, the REQ class sets them to orange to indicate a request, and the FAIL class sets them to red when they are in the "off" state.
By dynamically changing the className property based on the outcome of the HTTP GET request, the appearance of the switches is updated in the Node-RED dashboard to provide visual feedback to the user.
The Template node is responsible for customizing the appearance of the UI switches in the Node-RED dashboard. It adds CSS styles to the switches based on their status, such as whether they are on or off, or if there is a request being made.
Here's an overview of the CSS classes and their corresponding styles defined in the template node:
md-card.nr-dashboard-switch.SUCCESS and md-card.nr-dashboard-switch.REQ: These classes are applied to the UI switches when they are in the "on" state or when a request is being made. The switches appear with a black color.
md-card.nr-dashboard-switch.FAIL: This class is applied to the UI switches when they are in the "off" state. The switches appear with a red color.
[node-id="24bd5be440d33cda"].SUCCESS, [node-id="24bd5be440d33cda"].REQ, and [node-id="24bd5be440d33cda"].FAIL: These classes are applied to the UI switches with the specific Node ID ("24bd5be440d33cda"). They customize the background color of the switches based on their status, with yellow for "on" state, moccasin for a request, and light pink for "off" state.
By applying these CSS styles to the UI switches, the template node allows for visual feedback to indicate the state of the switches and their interaction with the underlying logic.
<style>
/* Specifying with selector for ON/OFF icons */
md-card.nr-dashboard-switch.SUCCESS ng-md-icon[icon="power"] {
color:black;
}
md-card.nr-dashboard-switch.SUCCESS ng-md-icon[icon="power_settings_new"] {
color:grey;
}
/* Or just the icon holder to address both ON/OFF*/
md-card.nr-dashboard-switch.REQ ng-md-icon {
color:orange;
}
md-card.nr-dashboard-switch.FAIL ng-md-icon {
color:red;
}
/* Or address every individual Node ID ON/OFF*/
[node-id="24bd5be440d33cda"].SUCCESS ui-icon[icon="power"]{
background-color:yellow;
}
[node-id="24bd5be440d33cda"].REQ ui-icon{
background-color:moccasin;
}
[node-id="24bd5be440d33cda"].FAIL ui-icon{
background-color:lightpink;
}
/*
moccasin
*/
</style>
Overall, this program provides a user interface to control RF plugs, with the ability to enable/disable switches, send HTTP requests to control the plugs, and update the UI based on the state of the switches and the success of th HTTP requests.
Setting the State
Code Explanation
This code handles the logic for managing the state of the three switches in the flow.
let state = flow.get('state') || false;
Retrieves the current state from the flow context using the key 'state'. If the state is not found (i.e., it is undefined or null), it assigns false as the default value to the state variable.
let enabled = msg.enabled;
Assigns the value of the enabled property from the msg object to the enabled variable. The msg object seems to contain additional information relevant to the switches' behavior.
The next three if statements each check the value of msg.topic to determine which switch is being referenced, and update state with the value of msg.payload. The updated state is then stored in the flow context with the key 'state[n]'.
if (msg.payload == 'get state')
This condition checks if msg.payload is equal to the string 'get state'. If true, it implies that a request has been made to retrieve the state, and the function returns an object with two properties: 'payload' and 'enabled'.
The 'payload' property contains the current state value for each switch.
The 'enabled' property retains its original value from msg.enabled.
Otherwise, the code reaches the return statement having updated the state . In this case, the function returns without any value.
Overall, this code maintains the state of three switches and allows retrieval of the state along with the value of the enabled property when a message with 'get state' as the payload is received.
The Switch nodes either side of HTTP Request node
Source code
secrets.py
ssid = '[network-id]'
password = '[network-password]'