8
8
from datetime import timedelta
9
9
from re import findall
10
10
from subprocess import check_output
11
-
11
+ from rpi_bad_power import new_under_voltage
12
12
import paho .mqtt .client as mqtt
13
13
import psutil
14
14
import pytz
18
18
19
19
try :
20
20
import apt
21
-
22
21
apt_disabled = False
23
22
except ImportError :
24
23
apt_disabled = True
34
33
OS_DATA [row [0 ]] = row [1 ]
35
34
36
35
mqttClient = None
37
- SYSFILE = "/sys/devices/platform/soc/soc:firmware/get_throttled"
38
36
WAIT_TIME_SECONDS = 60
39
37
deviceName = None
38
+ _underVoltage = None
40
39
41
40
class ProgramKilled (Exception ):
42
41
pass
@@ -65,6 +64,11 @@ def run(self):
65
64
self .execute (* self .args , ** self .kwargs )
66
65
67
66
67
+ def write_message_to_console (message ):
68
+ print (message )
69
+ sys .stdout .flush ()
70
+
71
+
68
72
def utc_from_timestamp (timestamp : float ) -> dt .datetime :
69
73
"""Return a UTC time from a timestamp."""
70
74
return UTC .localize (dt .datetime .utcfromtimestamp (timestamp ))
@@ -95,40 +99,28 @@ def on_message(client, userdata, message):
95
99
96
100
def updateSensors ():
97
101
payload_str = (
98
- '{"temperature": '
99
- + get_temp ()
100
- + ', "disk_use": '
101
- + get_disk_usage ("/" )
102
- + ', "memory_use": '
103
- + get_memory_usage ()
104
- + ', "cpu_usage": '
105
- + get_cpu_usage ()
106
- + ', "swap_usage": '
107
- + get_swap_usage ()
108
- + ', "power_status": "'
109
- + get_rpi_power_status ()
110
- + '", "last_boot": "'
111
- + get_last_boot ()
112
- + '", "last_message": "'
113
- + get_last_message ()
114
- + '"'
102
+ '{'
103
+ + f'"temperature": { get_temp ()} ,'
104
+ + f'"disk_use": { get_disk_usage ("/" )} ,'
105
+ + f'"memory_use": { get_memory_usage ()} ,'
106
+ + f'"cpu_usage": { get_cpu_usage ()} ,'
107
+ + f'"swap_usage": { get_swap_usage ()} ,'
108
+ + f'"power_status": "{ get_rpi_power_status ()} ",'
109
+ + f'"last_boot": "{ get_last_boot ()} ",'
110
+ + f'"last_message": "{ get_last_message ()} "'
115
111
)
116
112
if "check_available_updates" in settings and settings ["check_available_updates" ] and not apt_disabled :
117
- payload_str = payload_str + ', "updates": ' + get_updates ()
113
+ payload_str = payload_str + f ', "updates": { get_updates ()} '
118
114
if "check_wifi_strength" in settings and settings ["check_wifi_strength" ]:
119
- payload_str = payload_str + ', "wifi_strength": ' + get_wifi_strength ()
115
+ payload_str = payload_str + f ', "wifi_strength": { get_wifi_strength ()} '
120
116
if "external_drives" in settings :
121
117
for drive in settings ["external_drives" ]:
122
118
payload_str = (
123
- payload_str
124
- + ', "disk_use_'
125
- + drive .lower ()
126
- + '": '
127
- + get_disk_usage (settings ["external_drives" ][drive ])
119
+ payload_str + f', "disk_use_{ drive .lower ()} ": { get_disk_usage (settings ["external_drives" ][drive ])} '
128
120
)
129
121
payload_str = payload_str + "}"
130
122
mqttClient .publish (
131
- topic = "system-sensors/sensor/" + deviceName + " /state" ,
123
+ topic = f "system-sensors/sensor/{ deviceName } /state" ,
132
124
payload = payload_str ,
133
125
qos = 1 ,
134
126
retain = False ,
@@ -183,55 +175,31 @@ def get_wifi_strength(): # check_output(["/proc/net/wireless", "grep wlan0"])
183
175
184
176
185
177
def get_rpi_power_status ():
186
- _throttled = open (SYSFILE , "r" ).read ()[:- 1 ]
187
- _throttled = _throttled [:4 ]
188
-
189
- if "power_integer_state" in settings and settings ["power_integer_state" ]:
190
- return _throttled
191
- else :
192
- if _throttled == "0" :
193
- return "Everything is working as intended"
194
- elif _throttled == "1000" :
195
- return "Under-voltage was detected, consider getting a uninterruptible power supply for your Raspberry Pi."
196
- elif _throttled == "2000" :
197
- return "Your Raspberry Pi is limited due to a bad powersupply, replace the power supply cable or power supply itself."
198
- elif _throttled == "3000" :
199
- return "Your Raspberry Pi is limited due to a bad powersupply, replace the power supply cable or power supply itself."
200
- elif _throttled == "4000" :
201
- return "The Raspberry Pi is throttled due to a bad power supply this can lead to corruption and instability, please replace your changer and cables."
202
- elif _throttled == "5000" :
203
- return "The Raspberry Pi is throttled due to a bad power supply this can lead to corruption and instability, please replace your changer and cables."
204
- elif _throttled == "8000" :
205
- return "Your Raspberry Pi is overheating, consider getting a fan or heat sinks."
206
- else :
207
- return "There is a problem with your power supply or system."
178
+ return _underVoltage .get ()
208
179
209
180
210
181
def check_settings (settings ):
211
182
if "mqtt" not in settings :
212
- print ("Mqtt not defined in settings.yaml! Please check the documentation" )
213
- sys .stdout .flush ()
183
+ write_message_to_console ("Mqtt not defined in settings.yaml! Please check the documentation" )
214
184
sys .exit ()
215
185
if "hostname" not in settings ["mqtt" ]:
216
- print ("Hostname not defined in settings.yaml! Please check the documentation" )
217
- sys .stdout .flush ()
186
+ write_message_to_console ("Hostname not defined in settings.yaml! Please check the documentation" )
218
187
sys .exit ()
219
188
if "timezone" not in settings :
220
- print ("Timezone not defined in settings.yaml! Please check the documentation" )
221
- sys .stdout .flush ()
189
+ write_message_to_console ("Timezone not defined in settings.yaml! Please check the documentation" )
222
190
sys .exit ()
223
191
if "deviceName" not in settings :
224
- print ("deviceName not defined in settings.yaml! Please check the documentation" )
225
- sys .stdout .flush ()
192
+ write_message_to_console ("deviceName not defined in settings.yaml! Please check the documentation" )
226
193
sys .exit ()
227
194
if "client_id" not in settings :
228
- print ("client_id not defined in settings.yaml! Please check the documentation" )
229
- sys .stdout .flush ()
195
+ write_message_to_console ("client_id not defined in settings.yaml! Please check the documentation" )
230
196
sys .exit ()
197
+ if "power_integer_state" in settings :
198
+ write_message_to_console ("power_integer_state is deprecated please remove this option power state is now a binary_sensor!" )
231
199
232
200
233
201
def send_config_message (mqttClient ):
234
- print ("send config message" )
202
+ write_message_to_console ("send config message" )
235
203
mqttClient .publish (
236
204
topic = f"homeassistant/sensor/{ deviceName } /{ deviceName } Temp/config" ,
237
205
payload = '{"device_class":"temperature",'
@@ -304,15 +272,22 @@ def send_config_message(mqttClient):
304
272
retain = True ,
305
273
)
306
274
mqttClient .publish (
307
- topic = f"homeassistant/sensor/{ deviceName } /{ deviceName } PowerStatus/config" ,
308
- payload = f"{{\" name\" :\" { deviceName } PowerStatus\" ,"
275
+ topic = f"homeassistant/binary_sensor/{ deviceName } /{ deviceName } PowerStatus/config" ,
276
+ payload = '{"device_class":"problem",'
277
+ + f"\" name\" :\" { deviceName } UnderVoltage\" ,"
309
278
+ f"\" state_topic\" :\" system-sensors/sensor/{ deviceName } /state\" ,"
310
279
+ '"value_template":"{{value_json.power_status}}",'
311
280
+ f"\" unique_id\" :\" { deviceName .lower ()} _sensor_power_status\" ,"
312
281
+ f"\" availability_topic\" :\" system-sensors/sensor/{ deviceName } /availability\" ,"
313
282
+ f"\" device\" :{{\" identifiers\" :[\" { deviceName .lower ()} _sensor\" ],"
314
- + f"\" name\" :\" { deviceName } Sensors\" ,\" model\" :\" RPI { deviceName } \" , \" manufacturer\" :\" RPI\" }},"
315
- + f"\" icon\" :\" mdi:power-plug\" }}" ,
283
+ + f"\" name\" :\" { deviceName } Sensors\" ,\" model\" :\" RPI { deviceName } \" , \" manufacturer\" :\" RPI\" }}"
284
+ + f"}}" ,
285
+ qos = 1 ,
286
+ retain = True ,
287
+ )
288
+ mqttClient .publish (
289
+ topic = f"homeassistant/sensor/{ deviceName } /{ deviceName } PowerStatus/config" ,
290
+ payload = '' ,
316
291
qos = 1 ,
317
292
retain = True ,
318
293
)
@@ -349,7 +324,7 @@ def send_config_message(mqttClient):
349
324
if "check_available_updates" in settings and settings ["check_available_updates" ]:
350
325
# import apt
351
326
if (apt_disabled ):
352
- print ("import of apt failed!" )
327
+ write_message_to_console ("import of apt failed!" )
353
328
else :
354
329
mqttClient .publish (
355
330
topic = f"homeassistant/sensor/{ deviceName } /{ deviceName } Updates/config" ,
@@ -410,10 +385,10 @@ def _parser():
410
385
411
386
def on_connect (client , userdata , flags , rc ):
412
387
if rc == 0 :
413
- print ("Connected to broker" )
388
+ write_message_to_console ("Connected to broker" )
414
389
client .subscribe ("hass/status" )
415
390
else :
416
- print ("Connection failed" )
391
+ write_message_to_console ("Connection failed" )
417
392
418
393
419
394
if __name__ == "__main__" :
@@ -443,7 +418,8 @@ def on_connect(client, userdata, flags, rc):
443
418
try :
444
419
send_config_message (mqttClient )
445
420
except :
446
- print ("something whent wrong" )
421
+ write_message_to_console ("something whent wrong" )
422
+ _underVoltage = new_under_voltage ()
447
423
job = Job (interval = timedelta (seconds = WAIT_TIME_SECONDS ), execute = updateSensors )
448
424
job .start ()
449
425
@@ -454,11 +430,10 @@ def on_connect(client, userdata, flags, rc):
454
430
sys .stdout .flush ()
455
431
time .sleep (1 )
456
432
except ProgramKilled :
457
- print ("Program killed: running cleanup code" )
433
+ write_message_to_console ("Program killed: running cleanup code" )
458
434
mqttClient .publish (f"system-sensors/sensor/{ deviceName } /availability" , "offline" , retain = True )
459
435
mqttClient .disconnect ()
460
436
mqttClient .loop_stop ()
461
437
sys .stdout .flush ()
462
438
job .stop ()
463
439
break
464
-
0 commit comments