Integration With Xiaomi Rice Cooker

Tags: #<Tag:0x00007f1738265560> #<Tag:0x00007f1738265330>

Hello everyone, I’m trying to integrate the Xiaomi Rice Cooker (Aka: chunmi.cooker.normal2)

I configure the Xiaomi Mi IO Binding with my account and i get the token of the device, afterwards i added a miio:basic Thing with the ip and the token. The thing recognises the device correctly:

hardwareVersion ESP8266
mcuFirmware 0026
modelId chunmi.cooker.normal2
serialNumber 0E5CD9CF
vendor Xiaomi
wifiFirmware 1.5.0-dev(7efd021)

With the Execute Command Channel i tried different commands (Ex: getProp[“temperature”]) and i get always the same response:

result: [“waiting”,“0001”,“null”,“21”,“60”,"-1",“60”,“0407”,“050415”,“0003001a”,“0100”,“ffffffffffff011effff010000001516”]

looking the result and comparing with the plugin for Home Assistant i realize this result corresponds with:

“func”, “waiting”
“menu”, ,“0001”,
“stage”, “null”
“temp”, “21”
“t_func”, “60”
“t_precook”, “-1”
“t_cook”, “60”
“setting”, “0407”
“delay”, “050415”
“version”, “0003001a”
“favorite”, “0100”
“custom”, “ffffffffffff011effff010000001516”

And now my questions is,

There is a way to take this json and process the information to update Items?

Is possible to create a database json to support this device?

And i try to send commands and i successfully stop the cooking process sending this command set_func[“end”], maybe is possible to create a Switch to start and stop the cooking process.

Thanks in advance for the help.

If I recall right, currently indeed the support for the rice cookers is not there.

So to start, it would need a json file for yor device. You can create some base version of that by using the switch item that creates experimental support.

As the properties are not much like the other devices prob only very few channels are created.
Can you try separately the individual properties by testing the reponse to commands for the properties like this: get_prop["func"] and get_prop["menu"] etc…

If they respond, the created json db file can be extended to pull those properies.

 "func",
        "menu",
        "stage",
        "temp",
        "t_func",
        "t_precook",
        "t_cook",
        "setting",
        "delay",
        "version",
        "favorite",
        "custom",

In any case, when you do, please share the debug loggin so the responses can be seen. That will help creating the db file for your device.

Thanks Marcel for your reply.
I tried to get the properties as you said without success, I put below a trace of the log for some of the properties but the result for all is the same:

[DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: MIIO_INFO, result: {"life":165813,"token":"XXX","mac":"44:23:7C:FC:C7:4F","fw_ver":"1.3.6","hw_ver":"ESP8266","uid":"6352316527","model":"chunmi.cooker.normal2","mcu_fw_ver":"0026","wifi_fw_ver":"1.5.0-dev(7efd021)","ap":{"rssi":-60,"ssid":"WolfCave_IoT","bssid":"DC:39:6F:7D:47:58"},"netif":{"localIp":"192.168.30.59","mask":"255.255.255.0","gw":"192.168.30.1"},"mmfree":17496}, fullresponse: {"result":{"life":165813,"token":"XXX","mac":"44:23:7C:FC:C7:4F","fw_ver":"1.3.6","hw_ver":"ESP8266","uid":"6352316527","model":"chunmi.cooker.normal2","mcu_fw_ver":"0026","wifi_fw_ver":"1.5.0-dev(7efd021)","ap":{"rssi":-60,"ssid":"WolfCave_IoT","bssid":"DC:39:6F:7D:47:58"},"netif":{"localIp":"192.168.30.59","mask":"255.255.255.0","gw":"192.168.30.1"},"mmfree":17496},"id":3}

[INFO ] [.internal.handler.MiIoAbstractHandler] - Mi Device model MiJia Rice Cooker (chunmi.cooker.normal2) identified as: miio:unsupported, thingtype miio:basic. Does not matches thingtype miio:unsupported. Unexpected, unless manual override.

12:20:04.422 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 8, -1
12:20:04.423 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":9,"method":"get_prop","params":["func"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:20:04.745 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: GET_PROPERTY, result: ["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"], fullresponse: {"result":["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"],"id":9}
12:20:04.747 [DEBUG] [iio.internal.handler.MiIoBasicHandler] - Unexpected size different. Request size 1,  response size 12. (Req: ["func"], Resp:["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"])

12:21:29.222 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 8, -1
12:21:29.223 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":13,"method":"get_prop","params":["menu"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:21:29.487 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: GET_PROPERTY, result: ["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"], fullresponse: {"result":["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"],"id":13}
12:21:29.489 [DEBUG] [iio.internal.handler.MiIoBasicHandler] - Unexpected size different. Request size 1,  response size 12. (Req: ["menu"], Resp:["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"])

12:22:26.171 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 8, -1
12:22:26.172 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":16,"method":"get_prop","params":["temp"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:22:26.475 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: GET_PROPERTY, result: ["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"], fullresponse: {"result":["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"],"id":16}
12:22:26.476 [DEBUG] [iio.internal.handler.MiIoBasicHandler] - Unexpected size different. Request size 1,  response size 12. (Req: ["temp"], Resp:["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"])

12:24:06.288 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 8, -1
12:24:06.289 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":21,"method":"get_prop","params":["version"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:24:06.725 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: GET_PROPERTY, result: ["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"], fullresponse: {"result":["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"],"id":21}
12:24:06.726 [DEBUG] [iio.internal.handler.MiIoBasicHandler] - Unexpected size different. Request size 1,  response size 12. (Req: ["version"], Resp:["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"])


12:32:20.442 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 8, -1
12:32:20.443 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":38,"method":"get_prop","params":["all"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:32:20.934 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: GET_PROPERTY, result: ["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"], fullresponse: {"result":["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"],"id":38}
12:32:20.936 [DEBUG] [iio.internal.handler.MiIoBasicHandler] - Unexpected size different. Request size 1,  response size 12. (Req: ["all"], Resp:["waiting","0001","null","22","60","-1","60","0407","050415","0003001a","0100","ffffffffffff011effff010000001617"])

But i was investigating and i see the implementation in python someone made, here the link:

as i can see they get the properties with get_prop[“all”] and get the array like appear in openhab with the response.

There is too all the calls for the functions available for the rice cooker (“set_menu”, “set_start”, “set_func”, “get_temp_history”)

I tried to start a cooking program with success sending:
set_start[“0001E101000000000000800200A00069030103730000085A020000EB006B040103740000095A0400012D006E0501037400000A5A0401FFFF00700601047600000C5A0401052D0A0F3C0A1E91FF820E01FF05FF78826EFF10FF786E02690F0DFF826EFF691000FF826EFF69100069FF5AFF00000000000081E9”]

12:44:26.359 [DEBUG] [.internal.handler.MiIoAbstractHandler] - locs 9, -1
12:44:26.360 [DEBUG] [rnal.transport.MiIoAsyncCommunication] - Command added to Queue {"id":66,"method":"set_start","params":["0001E101000000000000800200A00069030103730000085A020000EB006B040103740000095A0400012D006E0501037400000A5A0401FFFF00700601047600000C5A0401052D0A0F3C0A1E91FF820E01FF05FF78826EFF10FF786E02690F0DFF826EFF691000FF826EFF69100069FF5AFF00000000000081E9"]} -> 192.168.30.59 (Device: 0E5CD9CF token: XXX Queue: 1)
12:44:26.873 [DEBUG] [.internal.handler.MiIoAbstractHandler] - Received response for 074a5fab type: UNKNOWN, result: ["ok"], fullresponse: {"result":["ok"],"id":66}

The long String is the cooking profile, all the profiles are in this link:
https://raw.githubusercontent.com/rytilahti/python-miio/5730f535d4691e0c2b4260cd7835b7a43ddc8ab0/miio/data/cooker_profiles.json

With the profiles for my model of rice cooker (MODEL_NORMAL_GROUP2) works perfectly, and i can stop the process with set_func[“end”]

Now the problem is, how we can get this array of the response get_prop[“all”] and update channels or items with this information, I’m not sure if the Xiaomi Mi IO Binding allows to get this JSON Array and use this information or maybe is necessary to create a new binding for this specific devices.
I hope this information can help anyone to integrate the Xiaomi Rice Cookers in Openhab.

Interesting, so it responds always with all properties… that is not directly supported by the miio binding … but there is maybe a way to cheat… we create a json db file with all of these properties for your device, set the max_properties to 12
So the binding will do a request for all of these properties in 1 go, as it will get the response with all the properties.Hence I expect it will properly map them to the appropriate field.

I don’t know if all of the codes can be mapped with OH transformations to proper values, otherwise indeed on the binding side something needs to be programed to decipher the code (esp the last one) to something meaninfull.
(in the miio binding speak, we need to create custom transformations for them)

So with the json db files we can create an action menu to send those start & stop commands easilly
see example like that here:

the matchvalue would be what you want to see in the dropdown.
e.g. the end command action would look something like this:

{
						"command": "set_func",
						"parameterType": "STRING",
						"condition": {
							"name": "matchValue",
								{
									"matchValue": "end"
								}
							]
						}
					},

We are getting closer, i create in conf/misc/miio/ a file chunmi.cooker.normal2.json with the content:

{
	"deviceMapping": {
		"id": [
			"chunmi.cooker.normal2"
		],
		"propertyMethod": "get_prop",
		"maxProperties": 12,
		"channels": [
			{
				"property": "get_prop",
				"maxProperties": 12,
				"friendlyName": "Status",
				"channel": "Status",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "",
				"friendlyName": "End Cooking",
				"channel": "RiceCooker_stop",
				"type": "String",
				"refresh": false,
				"actions": [
					{
						"command": "set_func",
						"parameterType": "STRING",
						"condition": {
							"name": "matchValue",
							"parameters": [
								{
									"matchValue": "end"
								}
							]
						}
					}
				]
			},
			{
				"property": "",
				"friendlyName": "Cooking Profile",
				"channel": "RiceCooker_start",
				"type": "String",
				"refresh": false,
				"ChannelGroup": "actions",
				"actions": [
					{
						"command": "set_start",
						"parameterType": "STRING"
					}
				]
			}
		]
	}
}

The maxProperties dosen’t work, i still see the “Unexpected size different. Request size 1, response size 12.” i tried too with max_properties but looks like has any effect, i have to say im using openHAB 2.5.9 Release Build not the latest OH3. I’m not sure if this parameter works for my version.

For the channels i created (RiceCooker_stop, RiceCooker_start) works well sending the String with a transforms and a small rule, i can live with it but still important to receive the updates from de device.

Any idea?

So you need for every property a channel, so it has all of them, in the right sequence as you get the response.
btw, in the channels no need for the maxproperties entry. The first one is fine as you have it
All these channels need refresh true, except for the one with the end cooking.
I would suggest actually to make some sort of action channel, which would be able to deal with start, end etc. what the condition matchvalue does is only execute that action if the value is matched, so for every type of command you would like to have executed through that channel, you add an action.

{
				"property": "func",
				"friendlyName": "function",
				"channel": "func",
				"type": "String",
				"refresh": true,
				"actions": []
			},

{
				"property": "menu",
				"friendlyName": "Menu",
				"channel": "menu",
				"type": "String",
				"refresh": true,
				"actions": []
			},

If you are on OH3 it supports a dropdown, so less need for transformations. In that case you can add something like below to the channel in the json

"stateDescription": {
					"options": [
						{
							"value": "end",
							"label": "End Program"
						},
						{
							"value": "start",
							"label": "Start Cooking"
						},
						{
							"value": "some blablabla that goes into the matchValue",
							"label": "Some nice description of it"
						}
					]
				},

one more thought to try out

the get_temp_history can probably freshed by adding a "customRefreshCommand": "get_temp_history" in the channel definition.

I created the JSON Database like this:

{
	"deviceMapping": {
		"id": [
			"chunmi.cooker.normal2"
		],
		"propertyMethod": "get_prop",
		"maxProperties": 12,
		"channels": [
			{
				"property": "func",
				"friendlyName": "Status",
				"channel": "RiceCooker_function",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": [],
				"stateDescription": {
					"readOnly": true,
					"options": [
						{
							"value": "running",
							"label": "Cooking"
						},
						{
							"value": "waiting",
							"label": "Waiting"
						},
						{
							"value": "autokeepwarm",
							"label": "Keeping rice warm"
						}
					]
				}
			},
			{
				"property": "menu",
				"friendlyName": "Menu",
				"channel": "RiceCooker_menu",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "stage",
				"friendlyName": "Stage",
				"channel": "RiceCooker_stage",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": [],
				"stateDescription": {
					"readOnly": true,
					"options": [
						{
							"value": "00000000ff",
							"label": "Quickly preheat"
						},
						{
							"value": "1",
							"label": "Water-absorbing"
						},
						{
							"value": "2",
							"label": "Boiling"
						},
						{
							"value": "3",
							"label": "Gelantinizing"
						},
						{
							"value": "4",
							"label": "Braising"
						},
						{
							"value": "5",
							"label": "Boiling"
						},
						{
							"value": "7",
							"label": "Boiling"
						},
						{
							"value": "8",
							"label": "Warm up rice"
						},
						{
							"value": "10",
							"label": "High temperature gelatinization"
						},
						{
							"value": "16",
							"label": "Cooking finished"
						},
						{
							"value": "null",
							"label": "Waiting"
						}
					]
				}
			},
			{
				"property": "temp",
				"friendlyName": "Temperature",
				"channel": "RiceCooker_temp",
				"type": "Number:Temperature",
				"unit": "CELCIUS",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "t_func",
				"friendlyName": "t_func",
				"channel": "RiceCooker_t_func",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "t_precook",
				"friendlyName": "t_precook",
				"channel": "RiceCooker_t_precook",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "t_cook",
				"friendlyName": "t_cook",
				"channel": "RiceCooker_t_cook",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "setting",
				"friendlyName": "setting",
				"channel": "RiceCooker_setting",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "delay",
				"friendlyName": "delay",
				"channel": "RiceCooker_delay",
				"type": "Number",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "version",
				"friendlyName": "version",
				"channel": "RiceCooker_version",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "favorite",
				"friendlyName": "favorite",
				"channel": "RiceCooker_favorite",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "custom",
				"friendlyName": "custom",
				"channel": "RiceCooker_custom",
				"type": "String",
				"refresh": true,
				"ChannelGroup": "",
				"actions": []
			},
			{
				"property": "",
				"friendlyName": "End Cooking",
				"channel": "RiceCooker_stop",
				"type": "String",
				"refresh": false,
				"actions": [
					{
						"command": "set_func",
						"parameterType": "STRING",
						"condition": {
							"name": "matchValue",
							"parameters": [
								{
									"matchValue": "end"
								}
							]
						}
					}
				]
			},
			{
				"property": "",
				"friendlyName": "Cooking Profile",
				"channel": "RiceCooker_start",
				"type": "String",
				"refresh": false,
				"ChannelGroup": "actions",
				"actions": [
					{
						"command": "set_start",
						"parameterType": "STRING"
					}
				]
			}
		]
	}
}

and i can see the updates in the interface

Now there are a lot of work for beautify this data and know what does mean (i have to look the result data when is running).

I created some stateDescription but indeed im not on OH3 and i don’t see any difference, i have to solve some incompatibilities i have with the OH3 and try.

Is a good idea to make a customRefreshCommand and see in a graph how is going the cooking process but the data format is quite complex, in this link is explained the format:

Colud be interesting to set some settings in the device too, but i think is necesary to make some rules for create the necessary octets for the device can understand or made a specific binding for make as cleaner and transparent as possible for the users.

Anyway thanks very much for the help, I will try to improve the JSON when i understand better the data and upgrade to the new OH3

1 Like

Cool that you managed to get it going.

With OH3 indeed the mappings will help a lot to make it more readable

If you can figure out how OH likes the data so it is usable in the graph we can create a transformation for it. Maybe some of the other channels also need a custom transformation to slice the right data from the response.

1 Like