{"id":4586,"date":"2024-02-28T12:00:02","date_gmt":"2024-02-28T20:00:02","guid":{"rendered":"https:\/\/www.cloudacm.com\/?p=4586"},"modified":"2024-02-28T11:28:01","modified_gmt":"2024-02-28T19:28:01","slug":"wemos-433-mhz-rf-receiver","status":"publish","type":"post","link":"https:\/\/www.cloudacm.com\/?p=4586","title":{"rendered":"Wemos 433 Mhz RF Receiver"},"content":{"rendered":"<p>I&#8217;ve been using RTL_433 with a SDR for a few years now with modest success. This setup will detect and identify a variety of 433Mhz sensor readings. The output is piped to a MQTT broker and from there the readings are presented graphically.<\/p>\n<p>At first this was done on a Raspberry Pi running a bash script on startup, with the following one liner command.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\">rtl_433 -F json | mosquitto_pub -h &lt;MQTT-Broker&gt; -i RTL_433 -l -t RTL_433\/SDR_FEED<\/pre>\n<p>Unpredictably, problems would arise when the process would hang and readings no longer were being received. This was addressed by placing the process under a supervisor task, details can be found in this post titled &#8220;Scheduled vs Supervised Tasks&#8221; <a href=\"https:\/\/www.cloudacm.com\/?p=3956\">https:\/\/www.cloudacm.com\/?p=3956<\/a>. Another issue discovered was that some sensors failed to be detected by the SDR. The standard antenna included with the SDR was replaced with a 433 Mhz tuned antenna, <a href=\"https:\/\/www.amazon.com\/Zerone-433MHZ-Antenna-Signal-Amplifier\/dp\/B07DMXSX45\">https:\/\/www.amazon.com\/Zerone-433MHZ-Antenna-Signal-Amplifier\/dp\/B07DMXSX45<\/a>. This improved coverage, but there were still some PIR sensors that were in dead spots. It was becoming clearer that the SDR had a hard limit and to get these dead spot sensors online, I would have to place some kind of bridging device closer to them.<\/p>\n<p>I had seen demonstrations of 433 Mhz RF modules being used with microcontrollers in this post, <a href=\"https:\/\/randomnerdtutorials.com\/decode-and-send-433-mhz-rf-signals-with-arduino\/\">https:\/\/randomnerdtutorials.com\/decode-and-send-433-mhz-rf-signals-with-arduino\/<\/a>. However, many of the demonstrations I found online used the RF modules as a wireless link between two microcontrollers. I had a Sonoff RF bridge available and looked into using it for the purpose of receiving and processing sensors. However, that would require hardware modifications and following a rather lengthy setup process with a narrow range of supported sensors.<\/p>\n<p>Along the way there were GitHub repos that caught my attention, <a href=\"https:\/\/github.com\/sui77\/rc-switch\/\">https:\/\/github.com\/sui77\/rc-switch\/<\/a> and <a href=\"https:\/\/github.com\/ninjablocks\/433Utils\">https:\/\/github.com\/ninjablocks\/433Utils<\/a>. It was this blog by Ray Wang that spelled out clearly what I was intending to do, <a href=\"https:\/\/rayshobby.net\/reverse-engineer-wireless-temperature-humidity-rain-sensors-part-1\/\">https:\/\/rayshobby.net\/reverse-engineer-wireless-temperature-humidity-rain-sensors-part-1\/<\/a>. This was further elaborated by Brad Hunting&#8217;s GitHub repo, <a href=\"https:\/\/github.com\/bhunting\/Acurite_00592TX_sniffer\">https:\/\/github.com\/bhunting\/Acurite_00592TX_sniffer<\/a>. From here out the pieces started to fall into place as I found more details on Brad&#8217;s blog, <a href=\"https:\/\/www.techspin.info\/\">https:\/\/www.techspin.info\/<\/a>.<\/p>\n<p>One of the key steps in getting the microcontroller to detect and decode the RF sensors was identifying the pattern. I used a logic analyzer to get the timings and sequences. From there I was able to display the sensor data with the microcontroller. This worked for my PIR motion sensors, temp\/humidity sensors, door reed switch sensors, and key fob controllers.<\/p>\n<p>I had some problems porting the code to work on the Wemos ESP8266. The code worked fine on the Arduino Uno, but the interrupts are handled differently on the ESP8266 microcontroller. The function called by attachInterrupt had to have ICACHE_RAM_ATTR defined. This video briefly explains some of the interrupt dependencies of the platform.<\/p>\n<p><iframe loading=\"lazy\" title=\"Tech Note 127 - ESP32\/8266 Hints and Tips for Reliable Interrupt Operation\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/WVK2Wx386XE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<p>Another problem I had was with the 433 Mhz receiver hardware. It operates at 5 volts and was causing a brownout of the Wemos when the microcontroller was attempting to boot. A workaround for this was to control the power to the receiver from the Wemos using a logic level shifter. The level shifter was already in use to shift the 5 volt signal from the receiver to 3.3 volts on the Wemos. Using a level shifter as a power supply is not recommended, but the low current draw of the receiver allowed it just this time. Here is the wiring of the components.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-4587\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever-300x300.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever-150x150.png 150w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever-768x768.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever-270x270.png 270w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Wemos_MQTT_433Mhz_Reciever.png 900w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Since this project was to detect dead spot PIR sensors, this is the code that was loaded on the Wemos. I liked that the library dependencies were minimal which made integrating functions from earlier code easier.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">\/*\r\n\r\n  Header\r\n\r\n  Title: Wemos ESP8266 433Mhz RF PIR MQTT Bridge\r\n  Version: 2\r\n  Filename: Wemos-433_MQTT_PIR-Sensor_Display_ver2.ino\r\n\r\n  Date: 12\/10\/2023\r\n  \r\n  Author: Patrick Gilfeather - CloudACM\r\n  https:\/\/www.cloudacm.com\r\n\r\n  Base Code based on\r\n  Convert RF signal into bits (PIR Sensor) \r\n  Written by : Ray Wang (Rayshobby LLC)\r\n  http:\/\/rayshobby.net\/?p=8998\r\n   \r\n  For ESP8266-Wemos, use LOLIN(WEMOS) D1, R2, and mini \r\n  \r\n\r\n*\/\r\n\r\n\r\n\/\/ Libraries and Declarations\r\n#include &lt;Arduino.h&gt;\r\n\r\n#include &lt;ESP8266WiFi.h&gt;\r\n\r\n#include &lt;PubSubClient.h&gt;\r\nWiFiClient espClient;\r\nPubSubClient MQTTclient(espClient);\r\nlong laststats = 0;\r\nint programflag = 0;\r\n\r\n\r\n\r\n\/\/ NTP Libraries, Declarations, and Variables\r\n#include &lt;NTPClient.h&gt;\r\n#include &lt;WiFiUdp.h&gt;\r\nWiFiUDP ntpUDP;\r\nNTPClient timeClient(ntpUDP, \"pool.ntp.org\");\r\n\/\/Week Days\r\nString weekDays[7]={\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"};\r\n\/\/Month names\r\nString months[12]={\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"};\r\n\r\n\r\n\r\n\r\n\/\/ Variables\r\n\r\n\/\/ MQTT Broker\r\nconst char* mqtt_server = \"#########\";     \/\/ Put your MQTT Broker here\r\n\r\n\/\/ Your WiFi credentials\r\nconst char* ssid =     \"#########\";               \/\/ Put your SSID here\r\nconst char* password = \"#########\";           \/\/ Put your PASSWORD here\r\n\r\nunsigned long lasttimeupdate = 0; \/\/ Time counter for periodic NTP time checks\r\nunsigned long lasttimereboot = 0; \/\/ Time counter for periodic reboots to avoid millis rollover\r\n\r\nADC_MODE(ADC_VCC);  \/\/ See comment block below for more details\r\n\/*\r\n  see - http:\/\/arduino.esp8266.com\/Arduino\/versions\/2.0.0-rc2\/doc\/libraries.html\r\n\r\n  ESP.getVcc() may be used to measure supply voltage. ESP needs to reconfigure the ADC at \r\n  startup in order for this feature to be available. Add the following line to the top of \r\n  your sketch to use getVcc:\r\n\r\n  ADC_MODE(ADC_VCC);\r\n\r\n  TOUT pin has to be disconnected in this mode.\r\n\r\n  Note that by default ADC is configured to read from TOUT pin using analogRead(A0), and \r\n  ESP.getVCC() is not available.\r\n\r\n *\/\r\n\r\n\/\/ ring buffer size has to be large enough to fit\r\n\/\/ data between two successive sync signals\r\n#define RING_BUFFER_SIZE  256\r\n\r\n#define SYNC_LENGTH 12200\r\n#define SYNC_RANGE  300  \/\/ Was hard coded to 400 but too much crosstalk\r\n\r\n#define BIT1_HIGH  1200\r\n#define BIT1_LOW   400\r\n#define BIT0_HIGH  400\r\n#define BIT0_LOW   1200\r\n#define BIT_RANGE  100  \r\n\r\n#define DATAPIN  2  \/\/ D2 is interrupt 1\r\n#define CONTROLPIN  4  \/\/ D4 is used to control power to the 433Mhz reciever module\r\n#define DELAYTIME 50  \/\/ 50 ms delay commonly used throughout code\r\n\r\nunsigned long timings[RING_BUFFER_SIZE];\r\nunsigned int syncIndex1 = 0;  \/\/ index of the first sync signal\r\nunsigned int syncIndex2 = 0;  \/\/ index of the second sync signal\r\nbool received = false;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\/\/ detect if a sync signal is present\r\nbool isSync(unsigned int idx) {\r\n  \/\/ check if we've received 4 squarewaves of matching timing\r\n  int i;\r\n\r\n  \/\/ check if there is a long sync period prior to the 4 squarewaves\r\n  unsigned long t = timings[(idx+RING_BUFFER_SIZE-i)%RING_BUFFER_SIZE];\r\n  \/\/ if(t&lt;(SYNC_LENGTH-400) || t&gt;(SYNC_LENGTH+400) ||\r\n  if(t&lt;(SYNC_LENGTH-SYNC_RANGE) || t&gt;(SYNC_LENGTH+SYNC_RANGE) ||\r\n    digitalRead(DATAPIN) != HIGH) {\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\/* Interrupt 1 handler *\/\r\nvoid ICACHE_RAM_ATTR handler() {\r\n  static unsigned long duration = 0;\r\n  static unsigned long lastTime = 0;\r\n  static unsigned int ringIndex = 0;\r\n  static unsigned int syncCount = 0;\r\n\r\n  \/\/ ignore if we haven't processed the previous received signal\r\n  if (received == true) {\r\n    return;\r\n  }\r\n  \/\/ calculating timing since last change\r\n  long time = micros();\r\n  duration = time - lastTime;\r\n  lastTime = time;\r\n\r\n  \/\/ store data in ring buffer\r\n  ringIndex = (ringIndex + 1) % RING_BUFFER_SIZE;\r\n  timings[ringIndex] = duration;\r\n\r\n  \/\/ detect sync signal\r\n  if (isSync(ringIndex)) {\r\n    syncCount ++;\r\n    \/\/ first time sync is seen, record buffer index\r\n    if (syncCount == 1) {\r\n      syncIndex1 = (ringIndex+1) % RING_BUFFER_SIZE;\r\n    } \r\n    else if (syncCount == 2) {\r\n      \/\/ second time sync is seen, start bit conversion\r\n      syncCount = 0;\r\n      syncIndex2 = (ringIndex+1) % RING_BUFFER_SIZE;\r\n      unsigned int changeCount = (syncIndex2 &lt; syncIndex1) ? (syncIndex2+RING_BUFFER_SIZE - syncIndex1) : (syncIndex2 - syncIndex1);\r\n      \/\/ changeCount must be 50 -- 24 bits x 2 + 2 for sync\r\n      if (changeCount != 50) {\r\n        received = false;\r\n        syncIndex1 = 0;\r\n        syncIndex2 = 0;\r\n      } \r\n      else {\r\n        received = true;\r\n      }\r\n    }\r\n\r\n  }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\/\/ MQTT Functions\r\n\r\nvoid callback(char* topic, byte* message, unsigned int length) {\r\n  \r\n  String messageTemp;\r\n  \r\n  for (int i = 0; i &lt; length; i++) {\r\n    messageTemp += (char)message[i];\r\n  }\r\n\r\n  if (String(topic) == \"Wemos-433\/UpdateTime\") {\r\n    if(messageTemp == \"CheckTime\"){\r\n          timeClient.update();\r\n    }\r\n  }  \r\n\r\n  if (String(topic) == \"Wemos-433\/Reboot\") {\r\n    if(messageTemp == \"Reboot\"){\r\n      ESP.restart();\r\n    }\r\n  }\r\n  \r\n}\r\n\r\n\r\n\r\nvoid reconnect() {\r\n  \/\/ Loop until we're reconnected\r\n  while (!MQTTclient.connected()) {\r\n    \/\/ Attempt to connect\r\n    if (MQTTclient.connect(\"Wemos-433\")) {\r\n      \/\/ Subscribe\r\n      \/\/ Do you not subscribe to my methods?\r\n      \/\/ Wemos-433\/# for everything, or Wemos-433\/Uptime for just the Uptime\r\n      MQTTclient.subscribe(\"Wemos-433\/#\");\r\n    } else {\r\n      \/\/ Wait 5 seconds before retrying\r\n      delay(5000);\r\n    }\r\n  }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid UpdateStats() {\r\n  \r\n  long stats = millis();\r\n  if (stats - laststats &gt; 5000) {\r\n    laststats = stats;\r\n\r\n    MQTTclient.publish(\"Wemos-433\/Firmware\", \"Wemos-433_MQTT_PIR-Sensor_Display_ver2\");     \r\n    String StringUptime = String(millis());\r\n    MQTTclient.publish(\"Wemos-433\/Uptime\", StringUptime.c_str());\r\n    String StringHWAddress = String(WiFi.macAddress());\r\n    MQTTclient.publish(\"Wemos-433\/HWAddress\", StringHWAddress.c_str());   \r\n    String StringWifiSignal = String(WiFi.RSSI());\r\n    MQTTclient.publish(\"Wemos-433\/WifiSignal\",StringWifiSignal.c_str());      \r\n    \r\n    String StringFreeHeapSize = String(ESP.getFreeHeap());\r\n    MQTTclient.publish(\"Wemos-433\/FreeHeapSize\",StringFreeHeapSize.c_str());  \r\n    String StringHeapFragmentation = String(ESP.getHeapFragmentation());\r\n    MQTTclient.publish(\"Wemos-433\/HeapFragmentation\",StringHeapFragmentation.c_str());  \r\n    String StringMaxFreeBlockSize = String(ESP.getMaxFreeBlockSize());\r\n    MQTTclient.publish(\"Wemos-433\/MaxFreeBlockSize\",StringMaxFreeBlockSize.c_str());  \r\n    String StringSketchSize = String(ESP.getSketchSize());\r\n    MQTTclient.publish(\"Wemos-433\/SketchSize\",StringSketchSize.c_str());  \r\n    String StringFreeSketchSpace = String(ESP.getFreeSketchSpace());\r\n    MQTTclient.publish(\"Wemos-433\/FreeSketchSpace\",StringFreeSketchSpace.c_str());  \r\n    String StringCpuFreqMHz = String(ESP.getCpuFreqMHz());\r\n    MQTTclient.publish(\"Wemos-433\/CpuFreqMHz\",StringCpuFreqMHz.c_str());\r\n    String StringChipId = String(ESP.getChipId());\r\n    MQTTclient.publish(\"Wemos-433\/ChipId\",StringChipId.c_str());  \r\n    String StringVcc = String(ESP.getVcc());\r\n    MQTTclient.publish(\"Wemos-433\/Vcc\",StringVcc.c_str());  \r\n\r\n    \/\/Get a Time Structure\r\n    String formattedTime = timeClient.getFormattedTime();\r\n    String StringformattedTime = String(formattedTime);\r\n    MQTTclient.publish(\"Wemos-433\/Time\",StringformattedTime.c_str());  \r\n\r\n    \/\/Get a Date Structure\r\n    time_t epochTime = timeClient.getEpochTime();\r\n    struct tm *ptm = gmtime ((time_t *)&amp;epochTime); \r\n    int monthDay = ptm-&gt;tm_mday;\r\n    int currentMonth = ptm-&gt;tm_mon+1;\r\n    String currentMonthName = months[currentMonth-1];\r\n    int currentYear = ptm-&gt;tm_year+1900;\r\n    \r\n    \/\/Publish complete date:\r\n    String StringcurrentDate = String(currentMonth) + \"\/\" + String(monthDay) + \"\/\" + String(currentYear);\r\n    MQTTclient.publish(\"Wemos-433\/Date\",StringcurrentDate.c_str());  \r\n    \r\n    \/\/Publish Epoch:\r\n    String StringEpochTime = String(timeClient.getEpochTime());\r\n    MQTTclient.publish(\"Wemos-433\/EpochTime\",StringEpochTime.c_str());  \r\n\r\n  }\r\n  \r\n}\r\n\r\n\r\n\r\n\r\n\r\nvoid setup() {\r\n  delay(DELAYTIME);                     \r\n  \r\n  pinMode(CONTROLPIN, OUTPUT);\r\n  digitalWrite(CONTROLPIN, LOW); \r\n  delay(DELAYTIME);                      \r\n  digitalWrite(CONTROLPIN, HIGH); \r\n  delay(DELAYTIME);                      \r\n  \r\n  pinMode(DATAPIN, INPUT); \r\n  attachInterrupt(digitalPinToInterrupt(DATAPIN), handler, CHANGE);\r\n\r\n  WiFi.mode(WIFI_STA);\r\n  WiFi.begin(ssid, password);\r\n  while (WiFi.status() != WL_CONNECTED)\r\n    {\r\n      \/\/ Just wait it out\r\n      delay(250);\r\n    }\r\n  \r\n  MQTTclient.setServer(mqtt_server, 1883);\r\n  MQTTclient.setCallback(callback);\r\n\r\n  timeClient.begin(); \/\/ Initialize a NTPClient to get time\r\n  timeClient.setTimeOffset(-25200);\r\n  \/\/ Set offset time in seconds to adjust for your timezone, for example:\r\n  \/\/ GMT -7 = -25200 (see - https:\/\/time.gov\/)\r\n  delay(1000);\r\n  timeClient.update();\r\n\r\n}\r\n\r\n\r\n\r\n\r\n\r\nint t2b(unsigned int t0, unsigned int t1) {\r\n  if (t0&gt;(BIT1_HIGH-BIT_RANGE) &amp;&amp; t0&lt;(BIT1_HIGH+BIT_RANGE) &amp;&amp;\r\n      t1&gt;(BIT1_LOW-BIT_RANGE) &amp;&amp; t1&lt;(BIT1_LOW+BIT_RANGE)) {\r\n    return 1;\r\n  } else if (t0&gt;(BIT0_HIGH-BIT_RANGE) &amp;&amp; t0&lt;(BIT0_HIGH+BIT_RANGE) &amp;&amp;\r\n             t1&gt;(BIT0_LOW-BIT_RANGE) &amp;&amp; t1&lt;(BIT0_LOW+BIT_RANGE)){\r\n    return 0;\r\n  }\r\n  return -1;  \/\/ undefined\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid loop() {\r\n  \r\n  if (!MQTTclient.connected()) {\r\n    reconnect();\r\n  } \r\n  MQTTclient.loop();\r\n  UpdateStats();\r\n\r\n  \/\/ Update time from NTP source every 1 day (24 * 60 * 60 * 1000 = 86400000 milli-seconds)\r\n  unsigned long timeupdate = millis();\r\n  if (timeupdate - lasttimeupdate &gt; 86400000) {\r\n    lasttimeupdate = timeupdate;\r\n    timeClient.update(); \r\n  }\r\n\r\n  \/\/ Reboot microcontroller every 30 day to avoid millis() rollover (30 * 24 * 60 * 60 * 1000 = 2592000000 milli-seconds)\r\n  unsigned long timereboot = millis();\r\n  if (timereboot - lasttimereboot &gt; 2592000000) {\r\n      \/\/ Reboot command\r\n      ESP.restart();\r\n  }\r\n  \r\n  if (received == true) {\r\n    \/\/ disable interrupt to avoid new data corrupting the buffer\r\n    \/\/ detachInterrupt(1);\r\n    detachInterrupt(digitalPinToInterrupt(DATAPIN));\r\n\r\n    \/\/ extract Device ID\r\n    unsigned int startIndex, stopIndex;\r\n    unsigned long deviceid = 0;\r\n    bool fail = false;\r\n    startIndex = (syncIndex1 + (0*8+0)*2) % RING_BUFFER_SIZE;\r\n    stopIndex = (syncIndex1 + (1*8+8)*2) % RING_BUFFER_SIZE;\r\n\r\n    for(int i=startIndex; i!=stopIndex; i=(i+2)%RING_BUFFER_SIZE) {\r\n    int bit = t2b(timings[i], timings[(i+1)%RING_BUFFER_SIZE]);\r\n    deviceid = (deviceid&lt;&lt;1) + bit;\r\n    if (bit &lt; 0) fail = true;\r\n    }\r\n\r\n    if (fail) {  \r\n        MQTTclient.publish(\"Wemos-433\/DecodeError\", \"Decoding error.\");     \r\n      }\r\n    else {\r\n    String StringDevID = String(deviceid);\r\n    MQTTclient.publish(\"Wemos-433\/DeviceID\", StringDevID.c_str());\r\n    }\r\n    \r\n\r\n    \r\n\r\n\r\n    \/\/ delay for 50 milli seconds to avoid repetitions\r\n    delay(DELAYTIME);\r\n    received = false;\r\n    syncIndex1 = 0;\r\n    syncIndex2 = 0;\r\n\r\n    \/\/ re-enable interrupt\r\n    \/\/ attachInterrupt(1, handler, CHANGE);\r\n    attachInterrupt(digitalPinToInterrupt(DATAPIN), handler, CHANGE);\r\n  }\r\n\r\n}<\/pre>\n<p>The hardware build initially was in a box. The Wemos module had its mini USB port exposed so that a USB cable could provide power. It also had a cut piece of wire that is 70 cm long as the antenna. This setup was rather unsightly since the box and long wires looked out of place.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4596 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components-1024x544.png\" alt=\"\" width=\"640\" height=\"340\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components-1024x544.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components-300x159.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components-768x408.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components-509x270.png 509w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Inside-Components.png 1132w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>I finally settled on installing it in a Tripp Lite TLP664USBB surge protector that included USB ports, <a href=\"https:\/\/tripplite.eaton.com\/6-outlet-surge-protector-with-4-usb-ports-6-foot-1800-joules-black~TLP664USBB\">https:\/\/tripplite.eaton.com\/6-outlet-surge-protector-with-4-usb-ports-6-foot-1800-joules-black~TLP664USBB<\/a>. This allowed the Wemos to get its power directly from the 5 volt USB ports. The power strip is used for other purposes and none of it looks odd or attention getting. I had to loop the antenna around the inside of the power strip. This didn&#8217;t present any problems as I was careful to isolate the electronics by sealing it with silicon calk. The Wemos module was placed so that the mini USB port was still accessible, should any programming need to be done later.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Power-Strip-Finished.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4593\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Power-Strip-Finished.png\" alt=\"\" width=\"667\" height=\"375\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Power-Strip-Finished.png 667w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Power-Strip-Finished-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2024\/02\/Tripp-Lite-Power-Strip-Finished-480x270.png 480w\" sizes=\"auto, (max-width: 667px) 100vw, 667px\" \/><\/a><\/p>\n<p>This project will likely expand as time goes on, with the option to decode multiple sensors types from a single microcontroller. But for now, this will do what I need.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been using RTL_433 with a SDR for a few years now with modest success. This setup will detect and identify a variety of 433Mhz sensor readings. The output is piped to a MQTT broker and from there the readings are presented graphically. At first this was done on a Raspberry Pi running a bash script on startup, with the following one liner command. rtl_433 -F json | mosquitto_pub -h &lt;MQTT-Broker&gt; -i RTL_433 -l -t RTL_433\/SDR_FEED Unpredictably, problems would arise&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.cloudacm.com\/?p=4586\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4586","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4586","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4586"}],"version-history":[{"count":6,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4586\/revisions"}],"predecessor-version":[{"id":4598,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/4586\/revisions\/4598"}],"wp:attachment":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4586"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4586"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4586"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}