-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmz2mqtt.py
140 lines (118 loc) · 5.18 KB
/
mz2mqtt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import asyncio
import logging
from queue import SimpleQueue
import paho.mqtt.client as mqtt_client
import mzlib
import yaml
async def main() -> None:
cmd_queue = SimpleQueue()
def create_msg(object, vehicleid, mqtt_topic, indent='/'):
for key in object:
if type(object[key]) == dict:
create_msg(object[key], vehicleid, mqtt_topic, indent + key + '/')
else:
mqttc.publish(mqtt_topic + '/' + str(vehicleid) + indent + key, object[key], 0, True)
return
async def get_and_publish(vehicle):
logging.info('get and publish data for ' + vehicle['vin'])
vehicle_status = await mazda_client.get_vehicle_status(vehicle['id'])
create_msg(vehicle_status, vehicle['vin'], mqtt_topic)
if vehicle['isElectric']:
vehicle_ev_status = await mazda_client.get_ev_vehicle_status(vehicle['id'])
create_msg(vehicle_ev_status, vehicle['vin'], mqtt_topic)
def on_connect(client, userdata, flags, rc):
if rc == 0:
logging.info("MQTT connected OK")
else:
logging.error("Bad connection Returned code=", rc)
def on_message(mosq, obj, msg):
msg.payload = str(msg.payload)
logging.info("received " + msg.topic + " " + msg.payload)
mqtt_cmd = msg.topic.split("/")
if mqtt_cmd[1].upper() == "SET":
cmd_queue.put(mqtt_cmd[2] + ':' + mqtt_cmd[3] + ':' + msg.payload)
logger = logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=logging.INFO)
# Read Config
with open('config.yaml', 'r') as configfile:
config = yaml.safe_load(configfile)
# Connect to myMazda
logging.info('Initialize myMazda')
mazda_user = config['mazda']['user']
mazda_password = config['mazda']['password']
mazda_region = config['mazda']['region'] or 'MME'
mazda_client = mzlib.Client(mazda_user, mazda_password, mazda_region, use_cached_vehicle_list=True)
status_wait = (config['status']['wait'] or 30) * 12
status_refreshwait = (config['status']['refreshwait'] or 2) * 60
# Connect to MQTT-Broker
logging.info('Initalize MQTT')
mqtt_broker_address = config['mqtt']['host']
mqtt_broker_port = config['mqtt']['port'] or 1883
mqtt_broker_user = config['mqtt']['user'] or None
mqtt_broker_password = config['mqtt']['password'] or None
mqtt_topic = config['mqtt']['topic'] or 'mz2mqtt'
mqtt_clientname = config['mqtt']['clientname'] or 'mz2mqtt'
mqttc = mqtt_client.Client(mqtt_clientname)
mqttc.enable_logger(logger)
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.username_pw_set(username=mqtt_broker_user, password=mqtt_broker_password)
mqttc.connect(mqtt_broker_address, mqtt_broker_port, 60)
mqttc.subscribe(mqtt_topic + '/' + 'SET/#', 0)
mqttc.loop_start()
# Get all Vehicles and publish base
logging.info('Get all vehicles')
try:
vehicles = await mazda_client.get_vehicles()
except Exception:
raise Exception("Failed to get list of vehicles")
# Publish vehicle data
logging.info('publish all vehicles base data')
for vehicle in vehicles:
create_msg(vehicle,vehicle['vin'], mqtt_topic)
# refresh all vehicle data at startup
try:
for vehicle in vehicles:
logging.info('refresh data for ' + vehicle['vin'])
await mazda_client.refresh_vehicle_status(vehicle['id'])
except:
logging.error('can not refresh all vehicles data')
await mazda_client.close()
logging.info('wait ' + str(status_refreshwait) + 's for data after refresh')
await asyncio.sleep(status_refreshwait)
# Main loop
try:
count = 0
while True:
# look for new API input
while not cmd_queue.empty():
r = cmd_queue.get_nowait()
mqtt_cmd = r.split(':')
match mqtt_cmd[1]:
case 'refresh':
found = False
for vehicle in vehicles:
if vehicle['vin'] == mqtt_cmd[0]:
found = True
logging.info('send refresh for ' + vehicle['vin'] + ' and wait' + str(status_refreshwait) + 's')
await mazda_client.refresh_vehicle_status(vehicle['id'])
await asyncio.sleep(status_refreshwait)
await get_and_publish(vehicle)
if not found:
logging.error('VIN ' + mqtt_cmd[0] + ' not found')
case _:
logging.error("invalid command: " + mqtt_cmd[1])
# wait time reached and get data
if count == 0:
for vehicle in vehicles:
await get_and_publish(vehicle)
count = status_wait
count -= 1
await asyncio.sleep(5)
except:
# Close the session
mqttc.loop_stop()
await mazda_client.close()
if __name__ == "__main__":
asyncio.run(main())