This commit is contained in:
Nigreon 2025-03-04 18:05:15 +01:00
parent d377fa89a4
commit 9e702af8c6
13 changed files with 639 additions and 133 deletions

View File

@ -0,0 +1,48 @@
{
"build": {
"arduino": {
"ldscript": "esp32c3_out.ld"
},
"core": "esp32",
"extra_flags": [
"-DARDUINO_XIAO_ESP32C3",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1"
],
"f_cpu": "160000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0x2886",
"0x0046"
],
[
"0x303a",
"0x1001"
]
],
"mcu": "esp32c3",
"variant": "nologo_esp32c3_super_mini"
},
"connectivity": [
"wifi"
],
"debug": {
"openocd_target": "esp32c3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "No logo ESP32C3 super mini",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 460800
},
"url": "",
"vendor": "No logo"
}

View File

@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DARDUINO_XIAO_ESP32S3",
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0x2886",
"0x0056"
],
[
"0x2886",
"0x8056"
]
],
"mcu": "esp32s3",
"variant": "XIAO_ESP32S3"
},
"connectivity": [
"bluetooth",
"wifi"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "Seeed Studio XIAO ESP32S3",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html",
"vendor": "Seeed Studio"
}

Binary file not shown.

View File

@ -0,0 +1,10 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
# bootloader.bin,, 0x1000, 32K
# partition table,, 0x8000, 4K
nvs, data, nvs, 0x9000, 20K,
otadata, data, ota, 0xe000, 8K,
ota_0, 0, ota_0, 0x10000, 2048K,
ota_1, 0, ota_1, 0x210000, 2048K,
uf2, app, factory,0x410000, 256K,
ffat, data, fat, 0x450000, 3776K,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 # bootloader.bin,, 0x1000, 32K
4 # partition table,, 0x8000, 4K
5 nvs, data, nvs, 0x9000, 20K,
6 otadata, data, ota, 0xe000, 8K,
7 ota_0, 0, ota_0, 0x10000, 2048K,
8 ota_1, 0, ota_1, 0x210000, 2048K,
9 uf2, app, factory,0x410000, 256K,
10 ffat, data, fat, 0x450000, 3776K,

View File

@ -0,0 +1,82 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x2886
#define USB_PID 0x0056
static const uint8_t LED_BUILTIN = 21;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 43;
static const uint8_t RX = 44;
/*
static const uint8_t SDA = 5;
static const uint8_t SCL = 6;
static const uint8_t SS = 44;
static const uint8_t MOSI = 9;
static const uint8_t MISO = 8;
static const uint8_t SCK = 7;
*/
static const uint8_t SDA = 6;
static const uint8_t SCL = 5;
static const uint8_t SS = 3;
static const uint8_t MOSI = 2;
static const uint8_t MISO = 1;
static const uint8_t SCK = 10;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A8 = 7;
static const uint8_t A9 = 8;
static const uint8_t A10 = 9;
static const uint8_t D0 = 1;
static const uint8_t D1 = 2;
static const uint8_t D2 = 3;
static const uint8_t D3 = 4;
static const uint8_t D4 = 5;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A8 = 7;
static const uint8_t A9 = 8;
static const uint8_t A10 = 9;
static const uint8_t D0 = 1;
static const uint8_t D1 = 2;
static const uint8_t D2 = 3;
static const uint8_t D3 = 4;
static const uint8_t D4 = 5;
static const uint8_t D5 = 6;
static const uint8_t D6 = 43;
static const uint8_t D7 = 44;
static const uint8_t D8 = 7;
static const uint8_t D9 = 8;
static const uint8_t D10 = 9;
static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
#endif /* Pins_Arduino_h */

Binary file not shown.

View File

@ -0,0 +1,28 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
static const uint8_t LED_BUILTIN = 8;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 21;
static const uint8_t RX = 20;
static const uint8_t SDA = 10;
static const uint8_t SCL = 9;
static const uint8_t SS = 7;
static const uint8_t MOSI = 6;
static const uint8_t MISO = 5;
static const uint8_t SCK = 4;
static const uint8_t A0 = 0;
static const uint8_t A1 = 1;
static const uint8_t A2 = 2;
static const uint8_t A3 = 3;
static const uint8_t A4 = 4;
static const uint8_t A5 = 5;
#endif /* Pins_Arduino_h */

View File

@ -10,24 +10,28 @@
[platformio] [platformio]
;default_envs = esp32_cc1101 ;default_envs = esp32_cc1101
default_envs = esp32c3_cdc_cc1101 ;default_envs = esp32c3_cdc_cc1101
;default_envs = rp2040 default_envs = esp32s3_cdc_sx1278
;default_envs = esp32c3_cdc_sx1278
boards_dir = boards boards_dir = boards
[libraries] [libraries]
arduinolog = https://github.com/1technophile/Arduino-Log.git#d13cd80 arduinolog = https://github.com/1technophile/Arduino-Log.git#d13cd80
arduinojson = arduinojson =
ArduinoJson ArduinoJson
finitespace/BME280
; ArduinoJson @ 7.0.4 ; ArduinoJson @ 7.0.4
; ArduinoJson @ 6.21.5 ; ArduinoJson @ 6.21.5
; ArduinoJson @ 5.13.4 ; deprecated ; ArduinoJson @ 5.13.4 ; deprecated
rtl_433_ESP = shchuko/rtl_433_ESP ;rtl_433_ESP = shchuko/rtl_433_ESP
rtl_433_ESP = https://github.com/NorthernMan54/rtl_433_ESP
[env] [env]
framework = arduino framework = arduino
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
;platform = espressif32@3.5.0 ;platform = espressif32@3.5.0
platform = espressif32@6.1.0 ;platform = espressif32@6.1.0
platform = espressif32
lib_ldf_mode = deep+ lib_ldf_mode = deep+
lib_deps = lib_deps =
sui77/rc-switch sui77/rc-switch
@ -35,8 +39,72 @@ lib_deps =
${libraries.arduinojson} ${libraries.arduinojson}
${libraries.rtl_433_ESP} ${libraries.rtl_433_ESP}
[env:esp32s3_cdc_sx1278]
board = seeed_xiao_esp32s3
build_flags =
'-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart
'-DARDUINO_USB_MODE=1'
'-DARDUINO_USB_CDC_ON_BOOT=1'
'-DLOG_LEVEL=LOG_LEVEL_TRACE'
;'-DOOK_FIXED_THRESHOLD=0x6E'
;'-DAUTOOOKFIX=1'
;'-DPUBLISH_UNPARSED=true'
;'-DSIGNAL_RSSI=true'
;'-DDEMOD_DEBUG=true'
'-DOOK_MODULATION=true' ; False is FSK, True is OOK
'-DRF_SX1278="SX1278"' ; CC1101 Transceiver Module
'-DRF_MODULE_DIO0=8' ; CC1101 pin GDO0
'-DRF_MODULE_DIO1=44' ; CC1101 pin GDO2
'-DRF_MODULE_DIO2=7'
'-DRF_MODULE_RST=43' ; CC1101 pin GDO2
;'-DRF_MODULE_SCK=9' ; SPI Clock
;'-DRF_MODULE_MISO=1' ; SPI Serial Output
;'-DRF_MODULE_MOSI=2' ; SPI Serial Input
'-DRF_MODULE_CS=3' ; SPI Chip select
'-DRF_MODULE_INIT_STATUS=true' ; Display transceiver config during startup
targets = upload
monitor_port = /dev/ttyACM0
monitor_speed = 115200
upload_port = /dev/ttyACM0
monitor_filters =
default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
; log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
[env:esp32c3_cdc_sx1278]
board = nologo_esp32c3_super_mini
build_flags =
'-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart
'-DARDUINO_USB_MODE=1'
'-DARDUINO_USB_CDC_ON_BOOT=1'
'-DLOG_LEVEL=LOG_LEVEL_TRACE'
;'-DOOK_FIXED_THRESHOLD=0x6E'
;'-DAUTOOOKFIX=1'
;'-DPUBLISH_UNPARSED=true'
;'-DSIGNAL_RSSI=true'
;'-DDEMOD_DEBUG=true'
'-DOOK_MODULATION=true' ; False is FSK, True is OOK
'-DRF_SX1278="SX1278"' ; CC1101 Transceiver Module
'-DRF_MODULE_DIO0=8' ; CC1101 pin GDO0
'-DRF_MODULE_DIO1=44' ; CC1101 pin GDO2
'-DRF_MODULE_DIO2=7'
'-DRF_MODULE_RST=44' ; CC1101 pin GDO2
;'-DRF_MODULE_SCK=9' ; SPI Clock
;'-DRF_MODULE_MISO=1' ; SPI Serial Output
;'-DRF_MODULE_MOSI=2' ; SPI Serial Input
'-DRF_MODULE_CS=3' ; SPI Chip select
'-DRF_MODULE_INIT_STATUS=true' ; Display transceiver config during startup
targets = upload
monitor_port = /dev/ttyACM0
monitor_speed = 115200
upload_port = /dev/ttyACM0
monitor_filters =
default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
; log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory
[env:esp32c3_cdc_cc1101] [env:esp32c3_cdc_cc1101]
board = esp32-c3-devkitm-1 board = nologo_esp32c3_super_mini
build_flags = build_flags =
'-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart '-DCONFIG_ESP_CONSOLE_UART=1' ; settings for esp32c3 without uart
'-DARDUINO_USB_MODE=1' '-DARDUINO_USB_MODE=1'
@ -76,9 +144,3 @@ build_flags =
targets = upload targets = upload
monitor_port = /dev/ttyACM0 monitor_port = /dev/ttyACM0
monitor_speed = 115200 monitor_speed = 115200
upload_port = /dev/ttyACM0
monitor_filters =
default ; Remove typical terminal control codes from input
time ; Add timestamp with milliseconds for each new line
; log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory

197
python/mqtt-systray.py Normal file → Executable file
View File

@ -7,7 +7,7 @@ import signal
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk, Gdk
gi.require_version('AppIndicator3', '0.1') gi.require_version('AppIndicator3', '0.1')
from gi.repository import AppIndicator3 as AppIndicator from gi.repository import AppIndicator3 as AppIndicator
@ -15,9 +15,6 @@ from gi.repository import AppIndicator3 as AppIndicator
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
import yaml import yaml
mqttprefix = "devices"
mqtthost = '192.168.67.1'
oldtmpfile = '' oldtmpfile = ''
oldalertcount = 0 oldalertcount = 0
menu = Gtk.Menu() menu = Gtk.Menu()
@ -26,17 +23,18 @@ fp = open("mqtt-systray.yaml")
conf = yaml.safe_load(fp) conf = yaml.safe_load(fp)
fp.close() fp.close()
mqttprefix = conf['config']['mqtt_prefix']
mqtthost = conf['config']['mqtt_host']
appindicator = AppIndicator.Indicator.new( appindicator = AppIndicator.Indicator.new(
'mqttalert', 'mqttalert',
'', '',
AppIndicator.IndicatorCategory.APPLICATION_STATUS) AppIndicator.IndicatorCategory.APPLICATION_STATUS)
def create_image(width, height, count): def create_image(width, height, count, color_circle):
# Generate an image and draw a pattern # Generate an image and draw a pattern
image = Image.new('RGB', (width, height), 'white') image = Image.new('RGB', (width, height), 'white')
dc = ImageDraw.Draw(image) dc = ImageDraw.Draw(image)
color_circle = 'green'
if count > 0: color_circle = 'red'
#dc.circle((width // 2, height // 2), height // 2, fill=color2) #dc.circle((width // 2, height // 2), height // 2, fill=color2)
radius = height // 2 radius = height // 2
ellipse_xy = (0, 0, radius*2, radius*2) ellipse_xy = (0, 0, radius*2, radius*2)
@ -54,42 +52,76 @@ def quit():
Gtk.main_quit() Gtk.main_quit()
def signal_handler(sig, frame): def signal_handler(sig, frame):
print('You pressed Ctrl+C!') #print('You pressed Ctrl+C!')
quit() quit()
def gtkquit(source): def gtkquit(source):
quit() quit()
def get_alert(devicea): def gtkdashboard(source):
for sensor in conf[devicea]['values'].keys(): Gtk.show_uri_on_window(None, conf['config']['dashboard_url'],int(Gdk.CURRENT_TIME))
if 'value' in conf[devicea]['values'][sensor] and (conf[devicea]['values'][sensor]['value'] > conf[devicea]['values'][sensor]['max'] or conf[devicea]['values'][sensor]['value'] < conf[devicea]['values'][sensor]['min']):
return True
return False
def get_alert2(devicea, sensora): def get_alert_text_warning(devicea, sensora):
alert_text = '' alert_text = ''
if 'value' in conf[devicea]['values'][sensora]: if 'value' in conf['devices'][devicea]['values'][sensora]:
if conf[devicea]['values'][sensora]['value'] > conf[devicea]['values'][sensora]['max']: if 'max_warning' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] > conf['devices'][devicea]['values'][sensora]['max_warning']:
alert_text = '!!HIGH!! ' alert_text = '!!high!! '
elif conf[devicea]['values'][sensora]['value'] < conf[devicea]['values'][sensora]['min']: elif 'min_warning' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] < conf['devices'][devicea]['values'][sensora]['min_warning']:
alert_text = '!!LOW!! ' alert_text = '!!low!! '
return alert_text return alert_text
def get_alert_text_critical(devicea, sensora):
alert_text = ''
if 'value' in conf['devices'][devicea]['values'][sensora]:
if 'max_critical' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] > conf['devices'][devicea]['values'][sensora]['max_critical']:
alert_text = '!!HIGH!! '
elif 'min_critical' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] < conf['devices'][devicea]['values'][sensora]['min_critical']:
alert_text = '!!LOW!! '
return alert_text
def get_alert_text(devicea, sensora):
alert_text = ''
if get_alert_text_critical(devicea, sensora) != '':
alert_text = get_alert_text_critical(devicea, sensora)
elif get_alert_text_warning(devicea, sensora) != '':
alert_text = get_alert_text_warning(devicea, sensora)
return alert_text
def alert_count_critical():
count = 0
for device in conf['devices']:
for sensor in conf['devices'][device]['values'].keys():
if get_alert_text_critical(device, sensor) != '': count = count + 1
return count
def alert_count_warning():
count = 0
for device in conf['devices']:
for sensor in conf['devices'][device]['values'].keys():
if get_alert_text_warning(device, sensor) != '': count = count + 1
return count
def alert_count(): def alert_count():
count = 0 count = 0
for device in conf: for device in conf['devices']:
for sensor in conf[device]['values'].keys(): for sensor in conf['devices'][device]['values'].keys():
if get_alert2(device, sensor) != '': count = count + 1 if get_alert_text_critical(device, sensor) != '' or get_alert_text_warning(device, sensor) != '': count = count + 1
return count return count
def get_icon(): def get_icon():
global oldtmpfile global oldtmpfile
if oldtmpfile!='': os.remove(oldtmpfile) if oldtmpfile!='': os.remove(oldtmpfile)
icon_path = tempfile.mktemp() icon_path = tempfile.mktemp()
oldtmpfile=icon_path oldtmpfile=icon_path
with open(icon_path, 'wb') as f: color = 'green'
create_image(64, 64, alert_count()).save(f, 'PNG') if alert_count_critical() > 0:
return icon_path color = 'red'
elif alert_count_warning() > 0:
color = 'yellow'
with open(icon_path, 'wb') as f:
create_image(64, 64, alert_count(), color).save(f, 'PNG')
return icon_path
#def menun2(deviceg): #def menun2(deviceg):
# itemn2 = [] # itemn2 = []
@ -107,17 +139,20 @@ def get_icon():
def build_menu(): def build_menu():
menu = Gtk.Menu() menu = Gtk.Menu()
for device1 in conf: for device1 in conf['devices']:
devname = conf[device1]['name'] devname = conf['devices'][device1]['name']
conf[device1]['menuitem'] = Gtk.MenuItem(devname) conf['devices'][device1]['menuitem'] = Gtk.MenuItem(label=devname)
submenu = Gtk.Menu() submenu = Gtk.Menu()
for sensor in conf[device1]['values'].keys(): for sensor in conf['devices'][device1]['values'].keys():
conf[device1]['values'][sensor]['menuitem'] = Gtk.MenuItem(sensor) conf['devices'][device1]['values'][sensor]['menuitem'] = Gtk.MenuItem(label=conf['devices'][device1]['values'][sensor]['name'])
submenu.append(conf[device1]['values'][sensor]['menuitem']) submenu.append(conf['devices'][device1]['values'][sensor]['menuitem'])
conf[device1]['menuitem'].set_submenu(submenu) conf['devices'][device1]['menuitem'].set_submenu(submenu)
menu.append(conf[device1]['menuitem']) menu.append(conf['devices'][device1]['menuitem'])
item_quit = Gtk.MenuItem('Quit') item_dashboard = Gtk.MenuItem(label='Open Dashboard')
item_dashboard.connect('activate', gtkdashboard)
menu.append(item_dashboard)
item_quit = Gtk.MenuItem(label='Quit')
item_quit.connect('activate', gtkquit) item_quit.connect('activate', gtkquit)
menu.append(item_quit) menu.append(item_quit)
@ -160,59 +195,59 @@ def build_menu():
# return menu # return menu
def update_menu(): def update_menu():
appindicator.set_menu(build_menu()) appindicator.set_menu(build_menu())
def set_value(topic, value): def set_value(topic, value):
global oldalertcount global oldalertcount
topicds = topic.rsplit("/", 1) topicds = topic.rsplit("/", 1)
devices=topicds[0] devices=topicds[0]
devices = devices.removeprefix(mqttprefix+'/') devices = devices.removeprefix(mqttprefix+'/')
conf[devices]['values'][topicds[1]]['value'] = float(value) conf['devices'][devices]['values'][topicds[1]]['value'] = float(value)
print("menu") #update_menu()
#update_menu()
alert_text = get_alert2(devices, topicds[1]) alert_text = get_alert_text(devices, topicds[1])
text='{}{}: {}'.format(alert_text, topicds[1], conf[devices]['values'][topicds[1]]['value']) text='{}{}: {} {}'.format(alert_text, conf['devices'][devices]['values'][topicds[1]]['name'], conf['devices'][devices]['values'][topicds[1]]['value'], conf['devices'][devices]['values'][topicds[1]]['unit'])
conf[devices]['values'][topicds[1]]['menuitem'].set_label(text) conf['devices'][devices]['values'][topicds[1]]['menuitem'].set_label(text)
#conf[devices]['values'][topicds[1]]['menuitem'].set_label("{}".format(conf[devices]['values'][topicds[1]]['value'])) #conf['devices'][devices]['values'][topicds[1]]['menuitem'].set_label("{}".format(conf['devices'][devices]['values'][topicds[1]]['value']))
devname = conf[devices]['name'] devname = conf['devices'][devices]['name']
#print(get_alert(devices)) #print(get_alert(devices))
#if get_alert(devices): devname = "! " + devname #if get_alert(devices): devname = "! " + devname
#if get_alert(devices): devname = "!!ALERT!! " + devname #if get_alert(devices): devname = "!!ALERT!! " + devname
#conf[devices]['menuitem'].set_label(devname) #conf['devices'][devices]['menuitem'].set_label(devname)
if oldalertcount != alert_count(): if oldalertcount != (alert_count()):
oldalertcount = alert_count() oldalertcount = alert_count()
appindicator.set_icon(get_icon()) appindicator.set_icon_full(get_icon(), "mqtt-icon")
os.system("notify-send '{}' '{}'".format(conf[devices]['name'], text)) os.system("notify-send '{}' '{}'".format(conf['devices'][devices]['name'], text))
def subscribe_mqtt(mqttc): def subscribe_mqtt(mqttc):
for device in conf: for device in conf['devices']:
#print(conf[device]) #print(conf[device])
for sensor in conf[device]['values'].keys(): for sensor in conf['devices'][device]['values'].keys():
#print(sensor) #print(sensor)
tosubscribe = "{}/{}/{}".format(mqttprefix, device, sensor) tosubscribe = "{}/{}/{}".format(mqttprefix, device, sensor)
mqttc.subscribe(tosubscribe, 0) mqttc.subscribe(tosubscribe, 0)
print(tosubscribe) print(tosubscribe)
def on_connect(mqttc, obj, flags, rc): def on_connect(mqttc, obj, flags, rc):
print("rc: " + str(rc)) print("rc: " + str(rc))
#def on_subscribe(mqttc, obj, mid, granted_qos): #def on_subscribe(mqttc, obj, mid, granted_qos):
# print("Subscribed: " + str(mid) + " " + str(granted_qos)) # print("Subscribed: " + str(mid) + " " + str(granted_qos))
def on_message(client, userdata, msg): def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload)) print(msg.topic+" "+str(msg.payload))
set_value(msg.topic, msg.payload) set_value(msg.topic, msg.payload)
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGINT, signal_handler)
appindicator.set_icon(get_icon()) appindicator.set_icon_full(get_icon(), "mqtt-icon")
appindicator.set_title('MQTT Alert') appindicator.set_title('MQTT Alert')
appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE) appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE)
appindicator.set_menu(build_menu()) appindicator.set_menu(build_menu())
set_value("model1/1/1/temperature1C", "10.1") set_value("model1/1/1/temperature1C", "25.1")
print(conf) #set_value("model2/2/2/humidity2", "75")
#print(conf)
mqttc = mqtt.Client() mqttc = mqtt.Client()
mqttc.on_message = on_message mqttc.on_message = on_message
@ -220,13 +255,13 @@ mqttc.on_connect = on_connect
#mqttc.on_subscribe = on_subscribe #mqttc.on_subscribe = on_subscribe
connected = False connected = False
while connected == False: while connected == False:
try: try:
mqttc.connect(mqtthost, 1883, 60) mqttc.connect(mqtthost, 1883, 60)
except: except:
time.sleep(5) time.sleep(5)
connected=False connected=False
else: else:
connected=True connected=True
mqttc.loop_start() mqttc.loop_start()
subscribe_mqtt(mqttc) subscribe_mqtt(mqttc)

View File

@ -1,22 +1,35 @@
model1/1/1: config:
name: "toto" mqtt_host: "192.168.67.1"
values: mqtt_prefix: "devices"
temperature1C: dashboard_url: "https://github.com/NorthernMan54/rtl_433_ESP"
name: "Temperature" devices:
min: 5 model1/1/1:
max: 20 name: "toto"
humidity1: values:
name: "Humidity" temperature1C:
min: 30 name: "Temperature"
max: 70 unit: "°C"
model2/2/2: humidity1:
name: "tata" name: "Humidity"
values: unit: "%"
temperature2C: min_critical: 20
name: "Temperature" min_warning: 30
min: 5 max_warning: 70
max: 20 max_critical: 80
humidity2: model2/2/2:
name: "Humidity" name: "tata"
min: 30 values:
max: 70 temperature2C:
name: "Temperature"
unit: "°C"
min_critical: 0
min_warning: 5
max_warning: 20
max_critical: 30
humidity2:
name: "Humidity"
unit: "%"
min_critical: 20
min_warning: 30
max_warning: 70
max_critical: 80

View File

@ -11,12 +11,19 @@ TOPIC_KEYS = [ "type", "model", "subtype", "channel", "id" ]
#default="devices[/type][/model][/subtype][/channel][/id]" #default="devices[/type][/model][/subtype][/channel][/id]"
prefix = "home/rtl_433" prefix = "home/rtl_433"
broker = "localhost" broker = "192.168.67.1"
port = 1883 port = 1883
altitude = 150
serialdev = "/dev/ttyACM0" serialdev = "/dev/ttyACM0"
serialspeed = 115200 serialspeed = 115200
def get_humidex(tdb, rh):
return round(tdb + 5 / 9 * ((6.112 * 10 ** (7.5 * tdb / (237.7 + tdb)) * rh / 100) - 10))
def get_sealevel_pressure(pres, altitude, temp):
return (pres / pow(1 - ((0.0065 *altitude) / (temp + (0.0065 *altitude) + 273.15)), 5.257));
def generate_topic(jsonin): def generate_topic(jsonin):
topic = prefix+'/devices' topic = prefix+'/devices'
@ -59,7 +66,15 @@ while True:
print("Error JSON, received {}".format(input)) print("Error JSON, received {}".format(input))
continue continue
#print(data) #print(data)
mqtt.publish(prefix+'/events', input.rstrip()) #mqtt.publish(prefix+'/events', input.rstrip())
if 'humidity' in data and 'temperature_C' in data:
data['humidex'] = get_humidex(data['temperature_C'], data['humidity'])
if 'pressure' in data:
data['pressure'] = get_sealevel_pressure(data['pressure'], altitude, data['temperature_C'])
data['pressure'] = round(data['pressure'], 1)
mqtt.publish(prefix+'/events', json.dumps(data))
prefix_device = generate_topic(data) prefix_device = generate_topic(data)
publish(data, prefix_device) publish(data, prefix_device)

View File

@ -82,6 +82,16 @@ def on_message(mqttc, obj, msg):
if 'humidity' not in recorddb[ref] or recorddb[ref]['humidity'] != value: if 'humidity' not in recorddb[ref] or recorddb[ref]['humidity'] != value:
measures += create_measure("humidity", currentts, tags, value) measures += create_measure("humidity", currentts, tags, value)
recorddb[ref]['humidity'] = value recorddb[ref]['humidity'] = value
if 'moisture' in jsonin:
value = int(jsonin['moisture'])
if 'moisture' not in recorddb[ref] or recorddb[ref]['moisture'] != value:
measures += create_measure("moisture", currentts, tags, value)
recorddb[ref]['moisture'] = value
if 'pressure' in jsonin:
value = float(jsonin['pressure'])
if 'pressure' not in recorddb[ref] or recorddb[ref]['pressure'] != value:
measures += create_measure("pressure", currentts, tags, value)
recorddb[ref]['humidity'] = value
if 'battery_ok' in jsonin: if 'battery_ok' in jsonin:
value = int(jsonin['battery_ok']) value = int(jsonin['battery_ok'])
if 'battery_ok' not in recorddb[ref] or recorddb[ref]['battery_ok'] != value: if 'battery_ok' not in recorddb[ref] or recorddb[ref]['battery_ok'] != value:

View File

@ -1,14 +1,22 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <rtl_433_ESP.h> #include <rtl_433_ESP.h>
#include <RCSwitch.h> #include <RCSwitch.h>
#include <Wire.h>
#include <BME280I2C.h>
#include <EnvironmentCalculations.h>
#include "Dictionary.h" #include "Dictionary.h"
#ifndef RF_MODULE_FREQUENCY
# define RF_MODULE_FREQUENCY 433.92
#endif
#define _DICT_PACK_STRUCTURES #define _DICT_PACK_STRUCTURES
#define LED 8 #define LED LED_BUILTIN
CC1101 radiotx = RADIO_LIB_MODULE; #define RCSWITCH_PIN 43
//CC1101 radiotx = RADIO_LIB_MODULE;
RCSwitch mySwitch = RCSwitch(); RCSwitch mySwitch = RCSwitch();
#ifndef RF_MODULE_FREQUENCY #ifndef RF_MODULE_FREQUENCY
@ -17,6 +25,8 @@ RCSwitch mySwitch = RCSwitch();
#define JSON_MSG_BUFFER 512 #define JSON_MSG_BUFFER 512
#define MINDELAY 10L #define MINDELAY 10L
#define ALTITUDE 150.0
#define DELAYLOCALSENSORS 30L
Dictionary<String, unsigned long> d1; Dictionary<String, unsigned long> d1;
@ -24,15 +34,35 @@ char messageBuffer[JSON_MSG_BUFFER];
rtl_433_ESP rf; // use -1 to disable transmitter rtl_433_ESP rf; // use -1 to disable transmitter
BME280I2C bme;
bool sensors_enabled;
int count = 0; int count = 0;
uint32_t lastts_localsensors = 0;
void rtl_433_Callback(char* message) { void rtl_433_Callback(char* message) {
//Serial.println("RTL433 Callback");
JsonDocument jsonDocument; JsonDocument jsonDocument;
deserializeJson(jsonDocument,message); deserializeJson(jsonDocument,message);
logJson(jsonDocument); logJson(jsonDocument);
count++; count++;
} }
JsonDocument analyzeTH_type1(JsonArray payloadrh) {
JsonDocument doc;
doc["moisture"] = payloadrh[5].as<int>();
int16_t payloadtemp = payloadrh[4].as<unsigned char>();
payloadtemp += payloadrh[3].as<unsigned char>() << 8;
doc["temperature_C"] = payloadtemp / 100.0;
doc["battery_ok"] = payloadrh[0].as<unsigned char>() & 0b00000001;
uint16_t payloadbat = payloadrh[2].as<unsigned char>();
payloadbat += payloadrh[1].as<unsigned char>() << 8;
doc["battery_V"] = ((payloadbat & 0b1111111110000000) >> 7) / 100.0;
doc["battery_percent"] = (payloadbat & 0b0000000001111111);
return doc;
}
void logJson(JsonDocument jsondata) { void logJson(JsonDocument jsondata) {
if(jsondata["model"].is<String>()) if(jsondata["model"].is<String>())
{ {
@ -42,6 +72,31 @@ void logJson(JsonDocument jsondata) {
if(!d1.contains(ref.c_str()) || millis() > (d1.get(ref.c_str()) + (MINDELAY * 1000)) || d1.get(ref.c_str()) > millis()) { if(!d1.contains(ref.c_str()) || millis() > (d1.get(ref.c_str()) + (MINDELAY * 1000)) || d1.get(ref.c_str()) > millis()) {
//Serial.println(ref.c_str()); //Serial.println(ref.c_str());
//if(d1.contains(ref.c_str())) { Serial.println(d1.get(ref.c_str())); } //if(d1.contains(ref.c_str())) { Serial.println(d1.get(ref.c_str())); }
if(jsondata["model"].is<String>() && jsondata["model"] == "RadioHead-ASK") {
JsonArray payloadrh = jsondata["payload"];
bool treatrh = 0;
if(jsondata["len"].as<int>() == 6 && ((payloadrh[0].as<unsigned char>() & 0b00010000 ) > 0)) {
treatrh = true;
//Serial.println("Analyse RH Payload");
JsonDocument adoc = analyzeTH_type1(payloadrh);
jsondata["moisture"] = adoc["moisture"];
jsondata["battery_ok"] = adoc["battery_ok"];
jsondata["battery_V"] = adoc["battery_V"];
jsondata["battery_percent"] = adoc["battery_percent"];
jsondata["temperature_C"] = adoc["temperature_C"];
}
if(treatrh == true) {
jsondata.remove("from");
jsondata.remove("to");
jsondata.remove("payload");
jsondata.remove("len");
jsondata.remove("flags");
jsondata.remove("mic");
jsondata.remove("duration");
}
}
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) #if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
char JSONmessageBuffer[measureJson(jsondata) + 1]; char JSONmessageBuffer[measureJson(jsondata) + 1];
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1); serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
@ -50,12 +105,97 @@ void logJson(JsonDocument jsondata) {
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER); serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
#endif #endif
d1.set(ref.c_str(), millis()); d1.set(ref.c_str(), millis());
ledblink();
Serial.println(JSONmessageBuffer); Serial.println(JSONmessageBuffer);
ledblink();
} }
} }
} }
/*
void logJsonRH(JsonDocument jsondata) {
if(jsondata["model"].is<String>() && jsondata["model"] == "RadioHead-ASK") {
JsonArray payloadrh = jsondata["payload"];
bool treatrh = 0;
if(jsondata["len"].as<int>() == 6 && ((payloadrh[0].as<unsigned char>() & 0b00010000 ) > 0)) {
treatrh = true;
//Serial.println("Analyse RH Payload");
JsonDocument adoc = analyzeTH_type1(payloadrh);
jsondata["moisture"] = adoc["moisture"];
jsondata["battery_ok"] = adoc["battery_ok"];
jsondata["battery_V"] = adoc["battery_V"];
jsondata["battery_percent"] = adoc["battery_percent"];
jsondata["temperature_C"] = adoc["temperature_C"];
}
if(treatrh == true) {
jsondata.remove("from");
jsondata.remove("to");
jsondata.remove("payload");
jsondata.remove("len");
jsondata.remove("flags");
jsondata.remove("mic");
jsondata.remove("duration");
}
}
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
char JSONmessageBuffer[measureJson(jsondata) + 1];
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
#else
char JSONmessageBuffer[JSON_MSG_BUFFER];
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
#endif
Serial.println(JSONmessageBuffer);
//Serial.print(JSONmessageBuffer);
//Serial.println();
//ledblink();
}
void logJsonAll(JsonDocument jsondata) {
// Serial.println(count);
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
char JSONmessageBuffer[measureJson(jsondata) + 1];
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
#else
char JSONmessageBuffer[JSON_MSG_BUFFER];
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
#endif
Serial.println(JSONmessageBuffer);
//ledblink();
}
*/
void sendBME280() {
JsonDocument jsonDocument;
jsonDocument["model"]="LocalSensors";
jsonDocument["protocol"]="Local Sensors";
//jsonDocument["channel"]=1;
//jsonDocument["id"]=1;
float temp(NAN), hum(NAN), pres(NAN);
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
EnvironmentCalculations::AltitudeUnit envAltUnit = EnvironmentCalculations::AltitudeUnit_Meters;
EnvironmentCalculations::TempUnit envTempUnit = EnvironmentCalculations::TempUnit_Celsius;
bme.read(pres, temp, hum, tempUnit, presUnit);
if(!isnan(pres) && !isnan(temp) && !isnan(hum)) {
//float temp2 = (int)(temp * 100 + .5);
//jsonDocument["temperature_C"]=(float)temp2 / 100;
jsonDocument["temperature_C"]=temp;
jsonDocument["humidity"]=(int8_t) roundf(hum);
//jsonDocument["pressure"]=EnvironmentCalculations::EquivalentSeaLevelPressure(ALTITUDE, temp, pres, envAltUnit, envTempUnit);
//float pres2 = (int)(pres * 10 + .5);
//jsonDocument["pressure"]=(float)pres2 / 10;
jsonDocument["pressure"]=pres;
logJson(jsonDocument);
}
}
void ledblink() { void ledblink() {
digitalWrite(LED, LOW); digitalWrite(LED, LOW);
delay(150); delay(150);
@ -63,19 +203,21 @@ void ledblink() {
} }
void setup() { void setup() {
Serial.setTxBufferSize(512);
//Serial.setTxTimeoutMs(100);
Serial.begin(115200); Serial.begin(115200);
delay(1000); delay(1000);
for (int i=0 ; i<10; i++) { //for (int i=0 ; i<10; i++) {
Serial.print("Hello"); // Serial.print("Hello");
delay(1000); // delay(1000);
} //}
if(SS != 21 || MOSI != 20 || MISO != 10 || SCK != 7) /* if(SS != 21 || MOSI != 20 || MISO != 10 || SCK != 7)
{ {
for ( ; ; ) { for ( ; ; ) {
Serial.println("Please define pin assignment for SPI in pins_arduino.h (~/.platformio/packages/framework-arduinoespressif32/variants/esp32c3) / SS: 21 MOSI : 20 MISO : 10 SCK : 7"); Serial.println("Please define pin assignment for SPI in pins_arduino.h (~/.platformio/packages/framework-arduinoespressif32/variants/esp32c3) / SS: 21 MOSI : 20 MISO : 10 SCK : 7");
delay(1000); delay(1000);
} }
} } */
pinMode(LED, OUTPUT); pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH); digitalWrite(LED, HIGH);
rf.initReceiver(RF_MODULE_RECEIVER_GPIO, RF_MODULE_FREQUENCY); rf.initReceiver(RF_MODULE_RECEIVER_GPIO, RF_MODULE_FREQUENCY);
@ -86,11 +228,17 @@ void setup() {
//d = new Dictionary(25); //d = new Dictionary(25);
//d("aa", "bb"); //d("aa", "bb");
//if(d1("aa")) { Serial.println("toto"); } //if(d1("aa")) { Serial.println("toto"); }
Wire.begin();
sensors_enabled = bme.begin();
} }
void loop() { void loop() {
rf.loop(); rf.loop();
if(sensors_enabled == true && (millis() > (lastts_localsensors + (DELAYLOCALSENSORS*1000)) || lastts_localsensors > millis())) {
lastts_localsensors = millis();
sendBME280();
}
if (Serial.available()) if (Serial.available())
{ {
// Read the JSON document from the "link" serial port // Read the JSON document from the "link" serial port
@ -106,15 +254,16 @@ void loop() {
if(doc["cmd"].as<String>().compareTo(String("rcsend"))==0) { if(doc["cmd"].as<String>().compareTo(String("rcsend"))==0) {
Serial.println("Transmit RCSwitch"); Serial.println("Transmit RCSwitch");
ledblink(); ledblink();
//rf.getModuleStatus(); //rf.disableReceiver();
rf.disableReceiver(); //radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_TX); //mySwitch.enableTransmit(RF_MODULE_GDO0);
mySwitch.enableTransmit(RF_MODULE_GDO0); mySwitch.enableTransmit(RCSWITCH_PIN);
mySwitch.setRepeatTransmit(8); //mySwitch.setRepeatTransmit(8);
mySwitch.setRepeatTransmit(5);
mySwitch.send(doc["value"].as<uint32_t>(), 24); mySwitch.send(doc["value"].as<uint32_t>(), 24);
mySwitch.disableTransmit(); //mySwitch.disableTransmit();
radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_RX); //radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
rf.enableReceiver(); //rf.enableReceiver();
//rf.getModuleStatus(); //rf.getModuleStatus();
} }
} }