initial commit from old development

This commit is contained in:
2021-06-07 17:03:43 +02:00
commit c1e8b31910
8 changed files with 354 additions and 0 deletions

236
BSHGateWay.py Normal file
View File

@@ -0,0 +1,236 @@
#!/usr/bin/python
#Bosch Home Automation <> MQTT Gateway
import requests, json, time
import paho.mqtt.client as mqtt
#Suppress http request warning
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class BSH:
#BSH Settings
IP_SHC = "192.168.178.20"
baseurl = 'https://' + IP_SHC + ':8444'
url = baseurl + '/remote/json-rpc'
states = ["childLock","value","position","armActivationDelayTime","alarmActivationDelayTime",
"walkState","petImmunityState","quality","faults","triggers","actuators","remainingTimeUntilArmed",
"state","path","enabled","devices","path","runningStartTime","runningEndTime","operationMode",
"setpointTemperature","setpointTemperatureForLevelComfort","setpointTemperatureForLevelEco",
"schedule","ventilationMode","low","boostMode","summerMode","on","calibrated","movingTimeTopToBottom",
"movingTimeBottomToTop","level","operationState","deviceId","switchState","operationMode",
"powerConsumption","energyConsumption","delay"]
#Mosquitto Settings
client_name = "BSH_Mosquitto_Client"
host_name = "192.168.178.36"
session = requests.Session()
AutomationRules = {}
DicAutomationRules = {}
Devices = {}
DicDevices = {}
Scenarios = {}
DicScenarios = {}
Rooms = {}
DicRooms = {}
client = mqtt.Client(client_name)
#get URL Headers
def getURLHeaders(self):
return {'Content-Type' : 'application/json'}
def getCertificate(self):
return ("./example-cert.pem","./example-key.pem")
#subscribe to Long Polling
def subscribe(self):
payload = [
{
"jsonrpc":"2.0",
"method":"RE/subscribe",
"id":"randomid",
"params": ["com/bosch/sh/remote/*", None]
}
]
return self.shc_request(payload)
#Start Long Polling and keep it 2 seconds open
def poll(self,pollId):
payload = [
{
"jsonrpc":"2.0",
"method":"RE/longPoll",
"id":"randomid",
"params": [pollId, 2]
}
]
return self.shc_request(payload)
#Post Polling data to SHC
def shc_request(self,payload):
postRequest = requests.post(self.url, data=json.dumps(payload), headers = self.getURLHeaders(),
verify = False, cert = self.getCertificate())
return json.loads(postRequest.text)[0]['result']
#Sent MQTT Debugging Message
def publishDebugMsg(self,msg):
self.client.publish("bsh/debug",msg,0,True)
#Get all BSH Decives
def getDevices(self):
getRequest = self.session.get("https://"+self.IP_SHC+":8444/smarthome/devices", verify=False,
cert = self.getCertificate(), headers = self.getURLHeaders())
return json.loads(getRequest.content)
#Get all BSH automation rules
def getAutomationRules(self):
getRequest = self.session.get("https://"+self.IP_SHC+":8444/smarthome/automation/rules", verify=False,
cert = self.getCertificate(), headers = self.getURLHeaders())
return json.loads(getRequest.content)
#Get all BSH scenarios
def getScenarios(self):
getRequest = self.session.get("https://"+self.IP_SHC+":8444/smarthome/scenarios", verify=False,
cert = self.getCertificate(), headers = self.getURLHeaders())
return json.loads(getRequest.content)
#Get all BSH rooms
def getRooms(self):
getRequest = self.session.get("https://"+self.IP_SHC+":8444/smarthome/rooms", verify=False,
cert = self.getCertificate(), headers = self.getURLHeaders())
contents = getRequest.content
return json.loads(contents)
#Generate a topic name for a device
def getTopicBase(self,dev):
topic = ""
if "roomId" in dev:
topic = "bsh/"+self.DicRooms[dev["roomId"]]["name"]+"/"+dev["name"].replace(" ","_")+"/"
else:
topic = "bsh/"+dev["name"].replace(" ","_")+"/"
return topic.replace("-","")
#update message for a single device
def publishDevice(self,id):
topicbase = self.getTopicBase(id)
getRequest = self.session.get("https://"+self.IP_SHC+":8444/smarthome/devices/"+id["id"]+"/services", verify=False,
cert = self.getCertificate(), headers = self.getURLHeaders())
data = json.loads(getRequest.content)
for id in data:
if "state" in id:
for s in self.states:
if s in id["state"]:
topic = topicbase+id["state"]["@type"]+"/"+s
payload = id["state"][s]
self.client.publish(topic,json.dumps(payload, indent=4, sort_keys=False),0,True)
self.publishDebugMsg(" Publishing topic: "+ topic + " Payload: "+ json.dumps(payload, indent=4, sort_keys=False))
#publish the initial status messages
def publishBSHStatus(self):
for x in self.Devices:
self.publishDevice(x)
#react to MQTT scenario requests:
def onMqttMessage(self, client, userdata, message):
#currently only react on trigger="ON"
if (str(message.payload.decode("utf-8")) == "ON"):
self.client.publish(message.topic,"OFF", 0,True)
for s in self.Scenarios:
topic = "bsh/scenarios/"+s["name"].replace(" ","_")+"/trigger"
if (topic == message.topic):
self.publishDebugMsg(" Scenario triggered: "+s["name"])
url = self.baseurl + "/smarthome/scenarios/"+s["id"]+"/triggers"
postRequest = requests.post(url, data="", headers = self.getURLHeaders(),
verify = False, cert = self.getCertificate())
data = json.loads(postRequest.text)[0]['result']
if "errorCode" in data:
self.publishDebugMsg("Error occured during Scenario Call:")
self.publishDebugMsg(data["errorCode"])
#subscribe to message to trigger scenarios
def subscribeToScenariosRequests(self):
for s in self.Scenarios:
topic = "bsh/scenarios/"+s["name"].replace(" ","_")+"/trigger"
self.publishDebugMsg("Adding subscribe: "+topic)
self.client.publish(topic,"OFF", 0,True)
self.client.subscribe(topic,0)
self.client.on_message = self.onMqttMessage
#set up the system: login to MQTT + get all needed data from the BSH
def __init__(self):
self.client.connect(self.host_name)
self.publishDebugMsg("Connecting to MQTT Server")
self.publishDebugMsg("Setting up the Environment...")
self.publishDebugMsg("Getting Room information")
self.Rooms = self.getRooms()
self.publishDebugMsg(str(len(self.Rooms))+" rooms found:")
for x in self.Rooms:
self.publishDebugMsg(x["id"]+":"+x["name"])
self.DicRooms.update({x["id"]:x})
self.publishDebugMsg("Getting Devices")
self.Devices = self.getDevices()
self.publishDebugMsg (str(len(self.Devices))+" Devices found:")
for x in self.Devices:
if "roomId" in x:
self.publishDebugMsg(x["id"]+":"+x["name"]+":"+self.DicRooms[x["roomId"]]["name"])
else:
self.publishDebugMsg(x["id"]+":"+x["name"])
self.DicDevices.update({x["id"]:x})
self.publishDebugMsg("Getting Automation Rules")
self.AutomationRules = self.getAutomationRules()
self.publishDebugMsg(str(len(self.AutomationRules))+" Automation rules found:")
for x in self.AutomationRules:
self.publishDebugMsg(x["id"]+":"+x["name"])
self.DicAutomationRules.update({x["id"]:x})
self.publishDebugMsg("Getting Senarios")
self.Scenarios = self.getScenarios()
self.publishDebugMsg (str(len(self.Scenarios))+" Scenarios found:")
for x in self.Scenarios:
self.publishDebugMsg(x["id"]+":"+x["name"])
self.DicScenarios.update({x["id"]:x})
self.publishDebugMsg("Posting initial states to MQTT Server")
self.publishBSHStatus()
self.publishDebugMsg("Subscribe to Service Requests")
self.subscribeToScenariosRequests()
def loop(self):
self.publishDebugMsg("Subscribing to Bosch Smart Home System...")
pollId = self.subscribe()
self.publishDebugMsg(pollId)
self.publishDebugMsg("Starting Polling...")
#Restart Long Polling every 5 seconds
while True:
result = self.poll(pollId)
if result != []:
for e in result:
if "deviceId" in e:
if e["deviceId"] in self.DicDevices:
self.publishDebugMsg("status change for: "+self.DicDevices[e["deviceId"]]["name"])
self.publishDevice(self.DicDevices[e["deviceId"]])
else:
self.publishDebugMsg("Unknown message received:")
self.publishDebugMsg('\n------------------------------------------------------ %d -\n' % len(result))
self.publishDebugMsg(json.dumps(e, indent=4, sort_keys=False))
self.client.loop_start()
time.sleep(5)
self.client.loop_stop()
BoschSmartHome = BSH()
BoschSmartHome.loop()

13
Dockerfile Normal file
View File

@@ -0,0 +1,13 @@
#$ docker build -t my-python-app .
#$ docker run -it --rm --name my-running-app my-python-app
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD [ "python", "./BSHGateWay.py" ]

16
example-cert.pem Normal file
View File

@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICkTCCAXkCBFmSY3YwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UEBhMCVVMwHhcN
MTcwODE1MDI1OTAyWhcNMTgwODE1MDI1OTAyWjANMQswCQYDVQQGEwJVUzCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIZyQlYQUCkFq8KUMlRysRDkC5zH
UZpZr4De4kVCQ10LMZeQLLsYtK/uPD71cNgzdoTNnDt1jHlDS8qJvq2c9yLXOO4l
R+1vvz9GEUo5apVhWoJ2/rvmvQgVwGIa98o1s+Veh+EZlAKlmxuPuVK44ewpPxFD
8fcEZzoCa4XiF14VrQrQAmC6/yWYk0QmQBCAx97UIE5XaLtZq8zhRTkhIHigMMQs
5SLAmzCQTD1fxjbjNmCrWFmpJ6c7oodmwWvO6ciYS/IOemnSoViQxiPq+Y2iIGYy
eP9JIF6eqljaMR9MQ9klwsBOlDTeUP7r5n7K6cD7wYjmK7nY8kxyYi6eR48CAwEA
ATANBgkqhkiG9w0BAQsFAAOCAQEAPk9wfZSJBP31Tc5azEcRNUNxiFj473mGdxXp
hsZAGrS/Pte0x+OGHhLDD2hkidIDhLrvbGN6OMTRtSouvuNYMSYbRuzfd8pe+0op
dsuj/4+utK2MXE11C7L29ygYbPHIN/pn6jbSx3B8N+O/NsDLUuCOqzfp9EB8iQio
6CplRrMb+cVj8MEmSD8qguAjUroozBunuxce72M82tyifRTByCx8xYwdRr8FGXfz
1na4WzvnBh05hv0ywNzklgkoTKZk2Jw1G733PvNJ423IXBkFzDc2NIml++5St8xw
Hu1IC1GIDzvaxuVMqF6ixLG8QGRXBKtpJgzFEY6qG/TkIeONBg==
-----END CERTIFICATE-----

28
example-key.pem Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCGckJWEFApBavC
lDJUcrEQ5Aucx1GaWa+A3uJFQkNdCzGXkCy7GLSv7jw+9XDYM3aEzZw7dYx5Q0vK
ib6tnPci1zjuJUftb78/RhFKOWqVYVqCdv675r0IFcBiGvfKNbPlXofhGZQCpZsb
j7lSuOHsKT8RQ/H3BGc6AmuF4hdeFa0K0AJguv8lmJNEJkAQgMfe1CBOV2i7WavM
4UU5ISB4oDDELOUiwJswkEw9X8Y24zZgq1hZqSenO6KHZsFrzunImEvyDnpp0qFY
kMYj6vmNoiBmMnj/SSBenqpY2jEfTEPZJcLATpQ03lD+6+Z+yunA+8GI5iu52PJM
cmIunkePAgMBAAECggEAZ7URWIPi4ZHfSQu5uwxxaz8NehUB7FcMGxNSZOxVPBtb
WLc82eGX1zGkxUfckNk5rf1Qa0kkX5G6j/Qq4o72z6hG4ORfFFcjpfItehzKC4p6
H7MckeLNo8Prj4GP7Cn6p46Ar/FkC5qlB+CYqqe0lc/HN1E6/zklS0j8mdyp+8cM
aFx+unY/TDIrXMreIgSYr2Ys5XO2kN22pP+0Uf+OZic2+9EQOkIImvHpX6FEVw5j
iXfGOYjwliiAtU0Ojso78ey5R/7SCRgpX2y3SCznquq0weVuqE0CrxecAlMgZRn8
DklCNeaB0OytDKIfix5Q0yNKQThul98MPGgpDKC1oQKBgQC61WPO5XGhCEc2r8UB
RkcSb792Tik/+JaOhZqwiZkx3jnBmU0HAb9VplOT1ciy4Kc4VilvwXNTbcUPx9KK
2UUxPt1S8G4sfVBvgPSG0NWeFoCCMV+UxT7VpBfJTXUCygooy8w/GwLXeAhOAIpz
F/Aj9Gz4F1YjsYG+Js7y7vxosQKBgQC4OAVfCDpNsJOLkY7csihbHhz+KohO7iOP
giNF5YI6XKbaRARX6UeLnE2KkqF+CJWfO9REDcPT6kG/EHjsjYVGqHxUfm2B4DO7
F/0JdE/5Smd8z7MxdDZDO7+TNMrtmpuQu57MGbk44mDAAXA954/M795PUVomxPx9
6r3/einEPwKBgDcwV5ZDIoid6GNYEoqo1s+0YMsylW7HILoi7yncy3r2mPr+LMm4
E2vagO+3g9yLDfpPQVg4vbdUQpTBwwiu24iLeFdKnFDaB4uYfSLhx2g2X2mV6hUJ
GuGC4l/dWIYlZlDcuo2djf5V/6YC9OLAnHgSeKnkQtayVY/06MbMH5VRAoGBALEw
URpDE7E+MeyAqOTmB6L8p+5ggpNIwrN5/OtyAXyZOXOfEH5uRv6l7H9o4iQTpbZv
GZALnVvraimYcnc0+AgqbsvmfvX47Ej8ncnGMlYZlsiaDkV2/epVQcMZeEZp+0+O
5wJxi5KHS3/i4k7ot4vq++1W1luMBUAn1XAx1JKJAoGBALN9hB2P0/36dyIUv2e9
cGT2PO8I60aGNgCvQMADfDlfxTlquHAWJwu88IuzDLvG22sgserNMo3kyCRUCxLp
cJZF+bSxKu2lVlbN9JJwBZSaz00l80xbYcjBIh9UhcXqKkeGbZhqF3nZ+C9VtFbD
sIxIhyn924TNCEb3FzebpYKq
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,17 @@
[Unit]
Description=BoschHomeAutomation 2 MQTT Gateway
After=multi-user.target
[Service]
Type=idle
Restart=always
RestartSec=30
StartLimitInterval=200
StartLimitBurst=5
WorkingDirectory=/opt/bsh-gateway
ExecStart=/opt/bsh-gateway/BSHGateWay.py
ExecStop=/bin/sleep 1
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
mac=`cat /sys/class/net/$(ip route get 8.8.8.8 | sed -n 's/.* dev \([^ ]*\).*/\1/p')/address`
arch=`uname -m`
### installing bsh gateway
echo -e "\033[36m Installing BSH Gateway.\033[0m"
if [ -d "/opt/bsh-gateway" ]; then
systemctl stop bsh-gateway.service
cp BSHGateWay.py /opt/bsh-gateway/
cp example-key.pem /opt/bsh-gateway/
cp example-cert.pem /opt/bsh-gateway/
else
mkdir /opt/bsh-gateway
cp BSHGateWay.py /opt/bsh-gateway/
cp example-key.pem /opt/bsh-gateway/
cp example-cert.pem /opt/bsh-gateway/
fi
cp bsh-gateway.service /lib/systemd/system/
chmod 644 /lib/systemd/system/bsh-gateway.service
systemctl daemon-reload
systemctl enable bsh-gateway.service
systemctl start bsh-gateway.service
echo -e "\033[32m Installation completed. BSH 2 MQTT Gateway is now up and running.\033[0m"

View File

@@ -0,0 +1,18 @@
#!/bin/bash
cd /tmp
echo -e "\033[36m BSH GateWay Service.\033[0m"
systemctl stop bsh-gateway.service
### Uninstalling BSH GateWay
echo -e "\033[36m Uninstalling BSH GateWay.\033[0m"
rm -rf /opt/bsh-gateway/
systemctl disable bsh-gateway.service
rm /lib/systemd/system/bsh-gateway.service
systemctl daemon-reload
echo -e "\033[32m Uninstall complete!\033[0m"

0
requirements.txt Normal file
View File