-
-
Save pascal-schetelat/4e31697a4c7e5fe7aeebe35d9053136b to your computer and use it in GitHub Desktop.
my_char = "PzLaM2ZqOx5Ks3NwIcJ1Sd6NeUvH7WfBrY9AbGgVtTnGhVyTmG8EjVu0TkFi4QClRoDpX" | |
mac_addr = '00:80:F4:xx:xx:xx' | |
replaceAll = mac_addr.replace(':', '') | |
def generatePasswd(str1=replaceAll, i=len(replaceAll), str2=my_char): | |
str3 = str1 | |
i2 = i | |
str4 = str2 | |
cArr = ['']*12 # 12 elements | |
if str3 != '': | |
i3 = 6 | |
if i2 >= 6: | |
substring = str3[-6:] | |
i4 = 0 | |
while (i4 < i2) & (i4 < i3): | |
hexToInt = int(f"0x{substring[i4]}",0) | |
i5 = 15 - (hexToInt % 15) | |
d2 = float(hexToInt) | |
i6 = i4 | |
d3 = float(i5) | |
round_ = int( | |
round(d3 ** 3.0) * 8 + | |
round(d3 ** 2.0) * 3 + | |
(i5 * 5)) % (len(str2) + 1) | |
i7 = i6 * 2 | |
idx = int(round(d2 ** 3.0) * 6 + | |
round(d2 ** 2.0) * 9 + | |
(hexToInt * 7) )% (len(str2) + 1) | |
cArr[i7] = str4[idx] | |
cArr[i7 + 1] = str4[round_] | |
i4 = i6 + 1 | |
i3 = 6 | |
return ''.join(cArr) | |
if __name__ == '__main__': | |
import requests | |
key = generatePasswd() | |
r = requests.get('https://192.168.xx.xx/rsa1/MeterInstantData', verify=False, auth=('m2madmin', key)) | |
r.json() | |
paths = { | |
"DELETE_INSTANCE_MIO_INPUT" : "/rsa1/MioInput;channel=", | |
"DELETE_INSTANCE_MIO_OUTPUT" : "/rsa1/MioOutput;channel=", | |
"DELETE_INSTANCE_MPR" : "/rsa1/MprEndpoint;channel=", | |
"DELETE_WIRELESS_INPUT" : "/rsa1/MioWirelessInput;slaveId=%d;channel=%d", | |
"DELETE_WIRELESS_METER" : "/rsa1/WirelessMeter;deviceAddress=", | |
"DELETE_WIRELESS_OUTPUT" : "/rsa1/MioWirelessOutput;slaveId=%d;channel=%d", | |
"DELETE_WIRELESS_PRO" : "/rsa1/WirelessProChannel;deviceAddress=", | |
"DELETE_WIRELESS_SENSOR" : "/rsa1/WirelessSensor;deviceAddress=", | |
"GET_BRANCH_METERS" : "/rsa1/BranchMeters", | |
"GET_CONNECTION_STATISTICS" : "/rsa1/WiserConnectionStatistics", | |
"GET_CONTROLLER" : "/rsa1/Controller", | |
"GET_EP_CONFIG_UPDATE_STATUS" : "/rsa1/EpConfigUpdateStatus ", | |
"GET_GATEWAY_KEY" : "/rsa1/GateWayKey", | |
"GET_INSTANCES_MPR" : "/rsa1/MprEndpoint/instances", | |
"GET_INSTANCE_MIO_INPUT" : "/rsa1/MioInput/instances", | |
"GET_INSTANCE_MIO_OUTPUT" : "/rsa1/MioOutput/instances", | |
"GET_MEASUREMENT_DATA" : "/rsa1/MeasurementData;sId=%d;ch=%d", | |
"GET_METER_CUMULATED_DATA" : "/rsa1/MeterCumulatedData", | |
"GET_METER_INSTANT_DATA" : "/rsa1/MeterInstantData", | |
"GET_PRODUCT_DETAILS" : "/rsa1/ProductDetails", | |
"GET_PRODUCT_INTERFACE" : "/fct/ProductInterface", | |
"GET_SYSTEM_UPGRADE_STATUS" : "/rsa1/SystemUpgradeStatus", | |
"GET_USAGE_METERS" : "/rsa1/UsageMeters", | |
"GET_USER_PREPAIRING" : "/rsa1/UserPreparing", | |
"GET_WIRELESS_DIAGNOSTIC" : "/rsa1/WirelessDiagnostic", | |
"GET_WIRELESS_INPUT" : "/rsa1/MioWirelessInput;slaveId=%d;channel=%d", | |
"GET_WIRELESS_INPUTS" : "/rsa1/MioWirelessInput/instances", | |
"GET_WIRELESS_METER" : "/rsa1/WirelessMeter;deviceAddress=", | |
"GET_WIRELESS_METERS" : "/rsa1/WirelessMeter/instances", | |
"GET_WIRELESS_METERS_LITE" : "/rsa1/WirelessMeterList/instances", | |
"GET_WIRELESS_METER_LITE" : "/rsa1/WirelessMeterInfo;dA=", | |
"GET_WIRELESS_OUTPUT" : "/rsa1/MioWirelessOutput;slaveId=%d;channel=%d", | |
"GET_WIRELESS_OUTPUTS" : "/rsa1/MioWirelessOutput/instances", | |
"GET_WIRELESS_PRO_LIST" : "/rsa1/WirelessProChannel/instances", | |
"GET_WIRELESS_PRO_LITE" : "/rsa1/WirelessProInfo;dA=", | |
"GET_WIRELESS_SENSOR" : "/rsa1/WirelessSensor;deviceAddress=", | |
"GET_WIRELESS_SENSORS" : "/rsa1/WirelessSensor/instances", | |
"GET_WIRELESS_SENSOR_LITE" : "/rsa1/WirelessSensorInfo;dA=", | |
"GET_WIRELESS_SENSOR_TEMPERATURE" : "/rsa1/TemperatureInfo;sId=", | |
"POST_BLINK_DEVICE" : "/rsa1/WirelessManager/methods/blinkDevice", | |
"POST_BUSINESS_INFO" : "/api/v1/fesb/provision", | |
"POST_EVE_METER" : "/rsa1/LoadStatus/methods/SetStandbyThreshold", | |
"POST_FIRMWARE_UPLOAD" : "/FirmwareUpload", | |
"POST_INIT_SYSTEM_UPGRADE" : "/rsa1/Controller/methods/initSystemUpgrade", | |
"POST_INSTANCE_MIO_CONTROL" : "/rsa1/Controller/methods/operateMio", | |
"POST_INSTANCE_MIO_INPUT" : "/rsa1/MioInput/instances", | |
"POST_INSTANCE_MIO_OUTPUT" : "/rsa1/MioOutput/instances", | |
"POST_INSTANCE_MPR" : "/rsa1/MprEndpoint/instances", | |
"POST_STATUS" : "/rsa1/LoadStatus/methods/GetStatus", | |
"PUT_BRANCH_METERS" : "/rsa1/BranchMeters", | |
"PUT_INSTANCE_MIO_INPUT" : "/rsa1/MioInput;channel=", | |
"PUT_INSTANCE_MIO_OUTPUT" : "/rsa1/MioOutput;channel=", | |
"PUT_INSTANCE_MPR" : "/rsa1/MprEndpoint;channel=", | |
"PUT_USER_PREPAIRING" : "/rsa1/UserPreparing", | |
"PUT_WIRELESS_CHANNEL" : "/rsa1/WirelessManager", | |
"PUT_WIRELESS_INPUT" : "/rsa1/MioWirelessInput;slaveId=%d;channel=%d", | |
"PUT_WIRELESS_METER" : "/rsa1/WirelessMeter;deviceAddress=", | |
"PUT_WIRELESS_OUTPUT" : "/rsa1/MioWirelessOutput;slaveId=%d;channel=%d", | |
"PUT_WIRELESS_SENSOR" : "/rsa1/WirelessSensor;deviceAddress=", | |
"SEM_IDENTIFICATION" : "/rsa1/SemIdentificationOpt", | |
"START_COMISSIONING" : "/rsa1/WirelessManager/methods/startCommissioning", | |
"STOP_COMISSIONING" : "/rsa1/WirelessManager/methods/stopCommissioning", | |
} |
Thanks alot man, u guys are the best!
btw, i figured out what was wrong when i wrote the last post. MAC is of course without ":"
Bonjour,
Ha je trouve enfin quelques personnes qui tentent de "hacker" la solution Wiser.
Dommage de voir qu'on est obligé de faire du reverse engineering pour communiquer avec.
L'API officielle ne suffit pas ?
https://exchange.se.com/devportal/api/wiser-home-essential-api
Avez vous tenté de mettre un "Man-In-The-Middle" et de sniffer les packet TCP avec TCPdump ou WireShark ?
Par ailleurs, sur les passerelles: EER31800, les deux bornes qui servent à communiquer avec les concentrateur de tore EER39000 est indiqué 9600baud, mais pas le protocole, serait-ce du RS232 ?
Je viens juste d’acheter la passerelle EER31800, je me demande si le server WEB est intégré et dans ce cas, simplement en simulant un navigateur client on doit pouvoir agir dessus (bien que cela risque d'être beaucoup moins pratique)
Avez vous avancé sur le sujet ?
From Developper Portal, API Wiser Home:
"/v1/hubs/{urn}/rooms/{roomId}/temperature": {
"get": {
"tags": [
"Rooms"
],
"description": "Get the temperatures for a specific room.",
"summary": "Fetch Room Temperature",
"operationId": "getRoomTemperature",
"parameters": [
{
"name": "roomId",
"in": "path",
"description": "The room identifier.",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"name": "from",
"in": "query",
"description": "The from date.",
"schema": {
"type": "string"
},
"example": "2024-02-01"
},
{
"name": "to",
"in": "query",
"description": "The to date.",
"schema": {
"type": "string"
},
"example": "2024-02-30"
},
{
"name": "urn",
"in": "path",
"description": "The URN of the hub in question, as returned by the /v1/hubs endpoint.",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Returns a room temperature or temperatures depending on the dates supplied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PartnerApiRoomTemperature"
}
}
}
},
"401": {
"description": "Returns an error message.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error401"
}
}
}
}
},
"security": [
{
"PersonalAccessToken": [
"read:wiser"
]
}
]
},
"patch": {
"tags": [
"Rooms"
],
"summary": "Set Temperature for a Room",
"operationId": "setTemperatureForRoom",
"description": "Temperature set points in the range 5 to 30 degrees Celsius can be set for a given room via the following API request.\r\nAttempts to set temperatures outside of this range will result in a 400 (bad request) response.",
"parameters": [
{
"name": "urn",
"in": "path",
"description": "The URN of the hub in question, as returned by the /v1/hubs endpoint.",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "roomId",
"in": "path",
"description": "The room identifier.",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"requestBody": {
"description": "The temperature in degrees C.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SetPointBody"
}
}
}
},
"responses": {
"200": {
"description": "Returns empty if temperature is successfully updated."
},
"400": {
"description": "Returns an error message."
},
"401": {
"description": "Returns an error message.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error401"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error404"
}
}
}
}
},
"security": [
{
"PersonalAccessToken": [
"write:wiser"
]
}
]
}
},
@rafaelallouche I am also doing some reverse engineering of the EM5 solution at the moment (and bricked a EER31600 in the process :'( )
Be VERY cautious as the connection between the gateway and the EM5 is NOT LOW VOLTAGE SAFE : there is indeed 24V between terminals, but the 0V terminal corresponds to half-wave rectified AC at low impedance (as if this interface was powered by a half diode bridge). Bridging the 0V terminal to the mains ground will trip the differential protection at the breaker panel.
You definitively want to use an isolation transformer to power the EM5 when tinkering with this interface. In the EER31600 there is an isolation chip between the terminal to the EM5 and the rest of the circuit.
The protocol itself is 9600 baud serial ; with an optocoupler it is should be possible to connect a USB-UART converter or any dev board to listen to traffic
1/ Push the button on the EER31800
2/ Get the key via HTTP GET on this URL : https://<wiser_ip>/rsa1/GateWayKey
3/ Convert the key and the MAC address to a password
Use this website : https://www.tutorialspoint.com/compile_java_online.php
Copy paste the class here : https://pastebin.com/raw/t59VjMkf
Add your MAC and GateWayKey.
4/ Send JSON data via HTTP POST to https://<wiser_ip>/rs/login
For exemple :
{
"username": "m2madmin",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
5/ A cookie is returned named SID, get the value of it (SID=yyyyyy)
6/ Make subsequent requests with that cookie by adding it in headers :
Cookie: SID=yyyyyy
It is now working for me 👍