Xiaomi magic cube - orientation reporting

I’ve gotten some Xiaomi kit to add to my king list home home automation devices (think this might finally push me into 3 figures)

Was just trawling over in one of the other forums and noticed that the guys at SmartThings have managed to capture the orientation of the magic cubes as an item: https://community.smartthings.com/t/release-xiaomi-magic-cube-controller-advanced-dth/85481

This lends yourself to sticking a little sticker on a single cube and coding that cube to behave totally differently depending on which face is up - Eg
One face for controlling your music
Another for your lighting
Another for your heating and so on

Has anyone bodged a solution like this? Is anyone looking at a patch for the code at present?

Thanks

you properbly already made the code for this, but there is my old code:

for light change:


rule "Xiaomi Cube change light"
//two cube modes changed by flip 90 degress 0 = intensity, 1 = color
when
    Item CubeAngel changed 
then




	if (CubeMode.state == 0) // change intensity
		{
		logInfo("rules", "Cube - Xiaomi Cube change light rule - intensity mode") 
		
    // for hue lights
    gLights_color_hue.members.forEach[ s |  
		
        
        //logInfo("rules", "Current item "+ s.name) 
          
        var HSBType CurrentState
        var DecimalType Current_H
        var PercentType Current_S
        var PercentType Current_B
                
        
        CurrentState = s.state as HSBType
        Current_H = CurrentState.hue 
        Current_S = CurrentState.saturation
        Current_B = CurrentState.brightness
       
        //logInfo("rules", "Current CurrentIntBritness "+ Current_B) 
            
        //need to have a variable witht the state
        var Number Angel = CubeAngel.state
        var Number New_B = Current_B + Angel
          
        //set limits
          if (New_B >= 100) { New_B = 100 }
       
          if (New_B <= 0) { New_B = 0 }
        
        //logInfo("rules", "New_B:" + New_B) 
               
                
        var String color = Current_H + "," + Current_S + "," + New_B
    
        s.sendCommand(color)   
		 
		 ]
     
     
    //logInfo("rules", "--------------None hue lights--------------------") 
    // for miHome and Yeelights
    gLights_Britness.members.forEach[ s |  
        
        //logInfo("rules", "Current item " + s.name + "state: " + s.state) 
        var Number Current_B
        
        if(s.state == NULL){
        //logInfo("rules", "set britness to 20 ") 
        Current_B = 20}
        else { Current_B = s.state }
       
        //logInfo("rules", "Current CurrentIntBritness "+ Current_B) 
            
        //need to have a variable witht the state
        var Number Angel = CubeAngel.state
        var Number New_B = Current_B + Angel
          
        //set limits
          if (New_B >= 100) { New_B = 100 }
       
          if (New_B <= 0) { New_B = 0 }
        
        //logInfo("rules", "New_B:" + New_B) 
               
        //new DecimalType()    
        //s.sendCommand(new DecimalType(New_B))
        //sendCommand.s(New_B)
        s.sendCommand(New_B)
        
		 ]
    
    
    
    
    }

	if (CubeMode.state == 1) // change color
		{
		logInfo("rules", "Cube Xiaomi Cube change light rule color mode") 
		logInfo("state", "Cube new angel "+CubeAngel.state) 
		
		gLights_color.members.forEach[ s |
	
        var HSBType CurrentState
        CurrentState = s.state as HSBType
        //CurrentState = Vindue_Color.state as HSBType
      
      
        var DecimalType new_H = CurrentState.hue
        var DecimalType CurrentIntColor = new_H
        
        //logInfo("rules", "Current CurrentIntColor "+CurrentIntColor) 
            
        //need to have a variable witht the state
        var Number Angel = CubeAngel.state
    
        var Number NewIntColor
        NewIntColor = CurrentIntColor + Angel
    
      
        //set limits
          if (NewIntColor > 255) { 
          //logInfo("rules", "NewIntColor > 255 substracting 255 : " + NewIntColor) 
          NewIntColor = NewIntColor -255 }
          if (NewIntColor < 0) { 
          //logInfo("rules", "NewIntColor < 0 adding 255: " + NewIntColor) 
          NewIntColor = NewIntColor + 255 }
        
        
        
        //logInfo("state", "NewIntColor "+NewIntColor) 
    
        var String RGB
        
            
        //var HSBType hsb  = HSBType::fromRGB(NewIntColor.intValue,100,100)
        
        RGB = NewIntColor + ",100,20"
        
        
        s.sendCommand(RGB) 
		 
		 ]
		}
	

end //-----------------------------------------------


Volume on chromecast:

rule "CubeChangeVolume: Xiaomi Cube flip180 (mode 2) and change angel "
when
     Item CubeAngel received update
then
	if (CubeMode.state == 2) // change volume, triggered by flip 180
    {
		logInfo("rules", "CubeChangeVolume: Xiaomi Cube flip180 (mode 2) and change angel") 
		//get current Volume
		//var Number CurrentIntVolume = CC_all_audioGroup_Volume.state	
    
    //use stue anlæg as referance
    var Number CurrentIntVolume = CC_all_audioGroup_Volume.state	
    
		
    //logInfo("rules", "CC_all_audioGroup_Volume: "+CC_all_audioGroup_dimmer.state) 
    
			if (CurrentIntVolume == NULL) {CurrentIntVolume = 0}
      logInfo("state", "Cube new angel "+CubeAngel.state) 
		 
		//logInfo("rules", "Current CurrentIntVolume "+CurrentIntVolume) 
		//logInfo("state", "Cube new angel "+CubeAngel.state) 

		//need to have a variable witht the state
		
		var Number Angel = CubeAngel.state 

		var Number NewIntVolume = CurrentIntVolume + (Angel / 4)
    
       
    
    //NewIntVolume = java.lang.Math.floor(NewIntVolume)//allow only whole numbers 
     
		//set limits
			if (NewIntVolume > 100) { NewIntVolume = 100 }
			if (NewIntVolume < 0) { NewIntVolume = 0 }

   
		CC_all_audioGroup_Volume.sendCommand(NewIntVolume)
    
		//CC_All_Volume_Dimmer.members.forEach[ s | s.sendCommand(NewIntVolume) ]
	}
		
	
end 

pause via free fall chromcast:

rule "CubeFreeFallAndMove: freefall "
when
     Channel 'mihome:sensor_cube:158d0001135c14:action' triggered
then
	var actionName = receivedEvent.getEvent()
    switch(actionName) {
     			
		case "FREE_FALL": { //pause/play CC
        if (CC_all_audioGroup_control.state == PLAY) { 
		//CC_all_audioGroup_control.sendCommand(PAUSE) 
		CC_All_Player_Control.members.forEach[ s | s.sendCommand(PAUSE) 
		]
		
		}
		else //CC_all_audioGroup_control.sendCommand(PLAY)
		CC_All_Player_Control.members.forEach[ s | s.sendCommand(PLAY) ]
			}
	}
	
end 

Proxy item control:

rule "Cube proxy rule CubeAngelWhite1"
when
     
     Item CubeAngelWhite1 received update 
     
then
	CubeAngel.state = CubeAngelWhite1.state
	
end 

rule "Cube proxy rule CubeAngelWhite2"
when
     
     Item CubeAngelWhite2 received update 
then
	CubeAngel.state = CubeAngelWhite2.state
	
end 

Change radio channel via cube on chromecast

rule "Xiaomi Cube change Radio channel"
//two cube modes changed by flip 90 degress 0 = intensity, 1 = color, 2 sound level, 3 = radio channel
when
    Item CubeAngel changed 
then
	if (CubeMode.state == 3) // change channel
  	{
		logInfo("rules", "Cube - Xiaomi Cube change Radio channel - cube mode 3") 
    //CONFIRM mode 10004=check  10002 =vælgradio  
    
       
		logInfo("state", "Cube new angel "+CubeAngel.state) 

		//need to have a variable witht the state
		
		var Number CubeAngel = CubeAngel.state
    var String ChannelURL
    var String ChannelName

		//set limits
		if (CubeAngel > 360) { CubeAngel = 360 }
		if (CubeAngel < -360) { CubeAngel = -360 }

		// 4 channels 
    // 1: 0-90
    // 2: 90 +
    // 3: 0- (-90)
    // 4: -90 +
 
 
   if	(CubeAngel < -90) { NbChromcastRadioChannelNumber.sendCommand(4) }
        else if (CubeAngel > -90 && CubeAngel <= 0) {NbChromcastRadioChannelNumber.sendCommand(3)}
        else if (CubeAngel > 0 && CubeAngel <= 90){ NbChromcastRadioChannelNumber.sendCommand(2)}
        else if (CubeAngel > 90){ NbChromcastRadioChannelNumber.sendCommand(1)}
        
        logInfo("rules","Radio channel = " + NbChromcastRadioChannelNumber.state)
   
		
   // get interpede channel number
   
  }
    
end //-----------------------------------------------



flip and move modes:

rule "Xiaomi Cube flip "
when

    Channel 'mihome:sensor_cube:158d0001135c14:action' triggered or
    Channel 'mihome:sensor_cube:158d0001108110:action' triggered
    
then
    //logInfo("rules", "Xiaomi cube set mode") 
    var actionName = receivedEvent.getEvent()
    switch(actionName) {
                
    case "FLIP90": {
      logInfo("rules", "case flip90 start") 

        if (CubeMode.state == 1) {
        
            CubeMode.sendCommand(0) 
            // XiaomiMiSmartHomeGateway_SoundVolume.sendCommand(30)
            // XiaomiMiSmartHomeGateway_SoundSelector.sendCommand(10004)
            }
        else{
        CubeMode.sendCommand(1)
        // XiaomiMiSmartHomeGateway_SoundVolume.sendCommand(30)
            // XiaomiMiSmartHomeGateway_SoundSelector.sendCommand(10004)
            }
        }    
        case "FLIP180": {
            if (CubeMode == 2) {CubeMode.sendCommand(0)
              //logInfo("rules", "Cube new angel "+CubeMode.state)  
              // XiaomiMiSmartHomeGateway_SoundVolume.sendCommand(30)
              // XiaomiMiSmartHomeGateway_SoundSelector.sendCommand(10004)
              }
            else {
            CubeMode.sendCommand(2)
            // logInfo("rules", "Cube new angel "+CubeMode.state)  
            // XiaomiMiSmartHomeGateway_SoundVolume.sendCommand(30)
            // XiaomiMiSmartHomeGateway_SoundSelector.sendCommand(10004)
           }
        }
        
        case "MOVE": {
          // XiaomiMiSmartHomeGateway_SoundVolume.sendCommand(30)
          // XiaomiMiSmartHomeGateway_SoundSelector.sendCommand(10004)
          CubeMode.sendCommand(3) //select radio channel
          // logInfo("rules", "Cube new angel "+CubeMode.state)  
          } 
    
    
		 }
    
end 

air shake and tap twice:


rule "Xiaomi Cube air shake and tap twice"
when
    Channel 'mihome:sensor_cube:158d0001135c14:action' triggered or
    Channel 'mihome:sensor_cube:158d0001108110:action' triggered or
    Channel 'mihome:sensor_cube:158d00011813ed:action' triggered
    
then
    var actionName = receivedEvent.getEvent()
    switch(actionName) {
	
		case "TAP_TWICE": {
		
		logInfo("state", "TAP_TWICE rule started") 
			//gLights_effect_SW.sendCommand(OFF)		
			//All_Lights_color_temperature_dimmer.members.forEach[ s | s.sendCommand(80) Thread::sleep(100) ]
      //String Hue , sat , Britness
      
			 gLights_color.sendCommand("0,0,60")
       gLights_Color_temperature_dimmer.sendCommand(60)
       CubeLightMode.sendCommand(0)
			 //CubeLightMode.postUpdate(0)
			 }
			
		case "SHAKE_AIR": {
			
    if(SwPartyMode.state != ON){SwPartyMode = ON}
      else 
        {SwPartyMode = OFF}
		/*
      gLights_color.members.forEach[light|
								
				//(new_H,new_S,new_B)
				sendCommand(light, (((Math::random * 255).intValue)) + "," + (((100.intValue))) + "," + (((30.intValue))))
				Thread::sleep(100)
		 ]
		*/
		}
	}
end

hope you can use it for inspiration maybe.

2 Likes

Thanks very much.

I coded roughly the same setup using proxy items (flip 180 to switch between lighting and music/Spotify control)
I also added an audio alert to gateway when switching modes, so I could tell which mode I was on when I flipped 180 (this would help me to not accidentally manage the wrong device)

In the end however, I reverted back to one cube per target function and extended the capability of the cube.

SpotiCube now does:

Flip 180: play party playlist
Double tap: chilled playlist
Drop: Radio
Rotate left / right: volume up / volume down
Shake: switch everything off

Since my wife and kids also use it (and quite like it) keeping it simple made more sense.

After all, I can control the lights with Alexa - but can’t use alexa to change music when my music is on loud (all my music runs through a total of 19 ceiling speakers in 6 different rooms)

Hi
I see you point and I find it hard sometimes to remember what combination is for what :smiley:
I also had an audio alert to check if the proxy item was set.

I really like the cube simple and non-screen interaction with your home automation is nicer I think than an interface.
Are you only playing one radio channel? do you have a way to change channel? I guess you could check if you are playing radio already and and change between a list of channels.
are you using it spotify with chromecast? I failed to find a way to cast a playlist chomecast unit.

When I am playing a Spotify playlist (so when my AV receiver is set to Spotify), a 90 degree flip skips track in playlist.
When I have data source set to net radio, i’ll Change to next saved station.
I am currently trying to resolve a big with the Yamaha binding to allow this - but have been caught up a little, since I am migrating my install to openhabian.

Ok, so you are not using chromecast if I understand you right.

I like you approach maybe I’ll change mine :slight_smile:

Yeah - I found too many things makes it api fil for those who didn’t code
it.
Keeping it simple enough means the cube is allowed to remain in sight on
the kitchen counter :stuck_out_tongue_winking_eye:

I have learnt that in order for me to have the time to do what I want at
home, I have to make my work accessible to everyone.
If they see the benefit, they leave me to play :grinning:

1 Like

I just received one of these cubes and was also hoping to report the orientation of the cube.

The use case for this is putting different colors on different sides of the cubes to change lighting.

Unfortunately it looks like the mihome API is simply not reporting this information so it doesn’t look like the binding can be modified to make this work.

Has anyone tried connecting to the cube directly in some way (zigbee USB dongle or through an Arduino)? It seems that you can directly connect the cube to Homey or SmartThings (as mentioned above) and you get orientation reporting.

I don’t think the hardware have this functionally. It only reports flips like 90 or 180 degrees, turning you can get directly from the binding and so on.

Way to get which face is up and then some :slight_smile:

The cube has no “UP” face.
You can (and I have previously done this) code to try cater for up down left right, buyt you have to make the assumption that the measurements on rotation are perfectly accurate and that all measurements are read and succesfully relayed to OpenHab.

My second attempt at doing this, was to use on of the actions (double tap) to reset a defined ‘up’ face. So when I double tapped, my code would reset the orientation to ‘the side with the blue sticker is now up’

In the end, I rethought my whole way of using the cube.

Rotation left and right are volume up and down.
Tip over is skip track.
Flip is next playlist
Shake is switch off
Double Tap is ‘chilled’ playlist.

Trying to get too much out of it, made it tricky to use (I originally wanted to drive both my music AND my lights with a single cube, so orientation would dictate what I was sending instructions to)

If you did want to do this, easiest is to say FLIP 180 changes device - and then use a proxy to relay your instructions to the correct device.

Ah - just saw your link…

Ignore my previous post.
I’ll have a look - I have a spare cube knocking about to play with anyway :slight_smile:

You might also find this of interest. :slight_smile:

You will have to use the ConBee USB dongle instead of the Xiaomi Gateway.
deCONZ SW can now be installed headless on Lin.

I’m looking for ideas on how to control colour with the cube. RGB input takes 3 int variables while each cube rotation can only adjust one. Do you guys make a whole list of nice RGB colours and cycle through it?