Skip to content

Commit

Permalink
clean up docs and repair subscription to commands
Browse files Browse the repository at this point in the history
- Handle re-subscription if MQTT broker restarts (#99)
- Simplify installation / setup documentation (#97)
- Repair bug in running shell to execute commands
  • Loading branch information
ironsheep committed May 1, 2023
1 parent 7160a83 commit 45a20f9
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 59 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# ChangeLog

Mon, 01 May 2023 16:51:08 -0600 v1.8.5

- Handle resubscription if MQTT broker restarts (#99)
- Simplify installation / setup documentation (#97)
- Repair bug in running shell to execute commands

Tue, 28 Mar 2023 23:24:03 -0600 v1.8.4

- Remove unused Requirements file from repo. (#92)
Expand Down
Binary file added Docs/images/Device-list.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/images/Discovered-Device.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 46 additions & 17 deletions ISP-RPi-mqtt-daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
except ImportError:
apt_available = False

script_version = "1.8.4"
script_version = "1.8.5"
script_name = 'ISP-RPi-mqtt-daemon.py'
script_info = '{} v{}'.format(script_name, script_version)
project_name = 'RPi Reporter MQTT2HA Daemon'
Expand Down Expand Up @@ -146,14 +146,21 @@ def clean_identifier(name):
def on_connect(client, userdata, flags, rc):
global mqtt_client_connected
if rc == 0:
print_line('* MQTT connection established',
console=True, sd_notify=True)
print_line('* MQTT connection established', console=True, sd_notify=True)
print_line('') # blank line?!
#_thread.start_new_thread(afterMQTTConnect, ())
mqtt_client_connected = True
print_line('on_connect() mqtt_client_connected=[{}]'.format(
mqtt_client_connected), debug=True)
client.on_publish = on_publish

# -------------------------------------------------------------------------
# Commands Subscription
if (len(commands) > 0):
print_line('MQTT subscription to {}/+ enabled'.format(command_base_topic), console=True, sd_notify=True)
mqtt_client.subscribe('{}/+'.format(command_base_topic))
else:
print_line('MQTT subscripton to {}/+ disabled'.format(command_base_topic), console=True, sd_notify=True)
# -------------------------------------------------------------------------

else:
print_line('! Connection error with result code {} - {}'.format(str(rc),
Expand All @@ -167,6 +174,13 @@ def on_connect(client, userdata, flags, rc):
# kill main thread
os._exit(1)

def on_disconnect(client, userdata, mid):
global mqtt_client_connected
mqtt_client_connected = False
print_line('* MQTT connection lost', console=True, sd_notify=True)
print_line('on_disconnect() mqtt_client_connected=[{}]'.format(
mqtt_client_connected), debug=True)
pass

def on_publish(client, userdata, mid):
#print_line('* Data successfully published.')
Expand All @@ -179,16 +193,27 @@ def on_publish(client, userdata, mid):
def on_subscribe(client, userdata, mid, granted_qos):
print_line('on_subscribe() - {} - {}'.format(str(mid),str(granted_qos)), debug=True, sd_notify=True)

shell_cmd_fspec = ''
def on_message(client, userdata, message):
print_line('on_message() Topic=[{}] payload=[{}]'.format(message.topic, message.payload), console=True, sd_notify=True, debug=True)
global shell_cmd_fspec
if shell_cmd_fspec == '':
shell_cmd_fspec = getShellCmd()
if shell_cmd_fspec == '':
print_line('* Failed to locate shell Command!', error=True)
# kill main thread
os._exit(1)

decoded_payload = message.payload.decode('utf-8')
command = message.topic.split('/')[-1]
print_line('on_message() Topic=[{}] payload=[{}] command=[{}]'.format(message.topic, message.payload, command), console=True, sd_notify=True, debug=True)

if command != 'status':
if command in commands:
print_line('- Command "{}" Received - Run {} {} -'.format(command, commands[command], decoded_payload), console=True, debug=True)
subprocess.Popen(["/usr/bin/sh", "-c", commands[command].format(decoded_payload)])
pHandle = subprocess.Popen([shell_cmd_fspec, "-c", commands[command].format(decoded_payload)])
output, errors = pHandle.communicate()
if errors:
print_line('- Command exec says: errors=[{}]'.format(errors), console=True, debug=True)
else:
print_line('* Invalid Command received.', error=True)

Expand Down Expand Up @@ -920,6 +945,17 @@ def getVcGenCmd():
print_line('Found vcgencmd(1)=[{}]'.format(desiredCommand), debug=True)
return desiredCommand

def getShellCmd():
cmd_locn1 = '/usr/bin/sh'
cmd_locn2 = '/bin/sh'
desiredCommand = cmd_locn1
if os.path.exists(desiredCommand) == False:
desiredCommand = cmd_locn2
if os.path.exists(desiredCommand) == False:
desiredCommand = ''
if desiredCommand != '':
print_line('Found sh(1)=[{}]'.format(desiredCommand), debug=True)
return desiredCommand

def getIPCmd():
cmd_locn1 = '/bin/ip'
Expand Down Expand Up @@ -1248,8 +1284,11 @@ def isAliveTimerRunning():

print_line('Connecting to MQTT broker ...', verbose=True)
mqtt_client = mqtt.Client()
# hook up MQTT callbacks
mqtt_client.on_connect = on_connect

mqtt_client.on_disconnect = on_disconnect
mqtt_client.on_publish = on_publish
mqtt_client.on_message = on_message

mqtt_client.will_set(lwt_sensor_topic, payload=lwt_offline_val, retain=True)
mqtt_client.will_set(lwt_command_topic, payload=lwt_offline_val, retain=True)
Expand Down Expand Up @@ -1281,16 +1320,6 @@ def isAliveTimerRunning():
error=True, sd_notify=True)
sys.exit(1)
else:
# -------------------------------------------------------------------------
# Commands Subscription
if (len(commands) > 0):
print_line('MQTT subscription to {}/+ enabled'.format(command_base_topic), console=True, sd_notify=True)
mqtt_client.on_message = on_message
mqtt_client.subscribe('{}/+'.format(command_base_topic))
else:
print_line('MQTT subscripton to {}/+ disabled'.format(command_base_topic), console=True, sd_notify=True)
# -------------------------------------------------------------------------

mqtt_client.publish(lwt_sensor_topic, payload=lwt_online_val, retain=False)
mqtt_client.publish(lwt_command_topic, payload=lwt_online_val, retain=False)
mqtt_client.loop_start()
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ Additional pages:

## Features

- Tested on Raspberry Pi's 2/3/4 with Jessie, Stretch and Buster
- Tested with Home Assistant v0.111.0 -> 2023.2.5
- Tested with Mosquitto broker v5.1 - v6.1.3
- Tested on Raspberry Pi's zero, 2, 3, and 4 with Jessie, Stretch, Buster, and Bullseye
- Tested with Home Assistant v0.111.0 -> 2023.4.6
- Tested with Mosquitto broker
- Data is published via MQTT
- MQTT discovery messages are sent so RPi's are automatically registered with Home Assistant (if MQTT discovery is enabled in your HA installation)
- MQTT authentication support
Expand Down Expand Up @@ -129,7 +129,7 @@ First install extra packages the script needs (select one of the two following c
### Packages for Ubuntu, Raspberry pi OS, and the like

```shell
sudo apt-get install git python3 python3-pip python3-tzlocal python3-sdnotify python3-colorama python3-unidecode python3-apt python3-paho-mqtt
sudo apt-get install git python3 python3-pip python3-tzlocal python3-sdnotify python3-colorama python3-unidecode python3-apt python3-paho-mqtt python3-requests
```

### Additional Packages for pure Ubuntu
Expand Down Expand Up @@ -234,6 +234,8 @@ password = {your mqtt password if your setup requires one}
Now that your config.ini is setup let's test!
**NOTE:** *If you wish to support remote commanding of your RPi then you can find additional configuration steps in [Setting up RPi Control from Home Assistant](./RMTCTRL.md) However, to simplifly your effort, please complete the following steps to ensure all is running as desired before you attempt to set up remote control.*
## Execution
### Initial Test
Expand Down Expand Up @@ -278,6 +280,8 @@ $ daemon : daemon video
# ^^^^^ now it is present
```
*NOTE: Yes, `video` is correct. This appears to be due to our accessing the GPU temperatures.*
### Choose Run Style
You can choose to run this script as a `systemd service` or as a `Sys V init script`. If you are on a newer OS than `Jessie` or if as a system admin you are just more comfortable with Sys V init scripts then you can use the latter style.
Expand Down Expand Up @@ -458,6 +462,15 @@ This data can be subscribed to and processed by your home assistant installation
## Troubleshooting
### Issue: I've updated my RPi OS and now I'm getting reporter script startup errors
Most often fix: _Re-add the video perms to the daemon group_
See Closed Issues: [#94](https://github.com/ironsheep/RPi-Reporter-MQTT2HA-Daemon/issues/94), [#98](https://github.com/ironsheep/RPi-Reporter-MQTT2HA-Daemon/issues/98)
We occasionaly have reports of users who updated their RPi afterwhich the RPI reporter Daemon script fails to start. The issue is that one of the packages updated appears to have reset the `daemon` group perminsions. For instructions on resetting the permissions to what is needed see: [Set up daemon account to allow access to temperature values](https://github.com/ironsheep/RPi-Reporter-MQTT2HA-Daemon#set-up-daemon-account-to-allow-access-to-temperature-values)
### Issue: Some of my RPi's don't show up in HA
Most often fix: _install the missing package._
Expand Down

0 comments on commit 45a20f9

Please sign in to comment.