Giter VIP home page Giter VIP logo

mi-home's Introduction

C# Library for using xiaomi smart gateway in your automation scenarious

Build project Tests Nuget License

This library provides simple and flexible C# API for Xiaomi Mi Home devices.

Currently supports only Gateway version 2 (DGNWG02LM), Air Humidifier (zhimi.humidifier.v1), Mi Robot vacuum (rockrobo.vacuum.v1) and several sensors. See the pictures below.

smart-home

humidifier mirobot

gateway temperature_sensor socket_plug motion_sensor motion_sensor_2 door_window_sensor aqara_door_window_sensor water_sensor smoke_sensor switch wired wall switch sensor_weather wireless dual wall switch aqara_cube_sensor

Table of Contents

  1. Installation
  2. Setup Gateway
  3. Basic scenario
  4. Supported devices

via nuget package manager

Install-Package MiHomeLib

or

dotnet add package MiHomeLib

or install via GitHub packages

Before using this library you should setup development mode on your gateway, instructions how to do this.
This mode allows to work with the gateway via UDP multicast protocol.

Warning 1: If you bought a newer revision of Mi Home Gateway (labels in a circle)

It could be possible that ports on your gateway required for UDP multicast traffic are closed.
Before using this library ports must be opened. Check this instruction.

Warning 2: Mi Home Gateway uses udp multicast for messages handling, so your app must be hosted in the same LAN as your gateway. If it is not you have to use multicast routers like udproxy or igmpproxy or vpn bridging.

Warning 3: If your app is running on windows machine, make sure that you disabled virtual network adapters like VirtualBox, Hyper-V, Npcap, pcap etc. Because these adapters may prevent proper work of multicast traffic between your machine and gateway

Get all devices in the network

public static void Main(string[] args)
{
    // gateway password is optional, needed only to send commands to your devices
    // gateway sid is optional, use only when you have 2 gateways in your LAN
    // using var miHome = new MiHome("gateway password", "gateway sid");
    using var miHome = new MiHome();
   
    miHome.OnAnyDevice += (_, device) =>
    {
        Console.WriteLine($"{device.Sid}, {device.GetType()}, {device}"); // all discovered devices
    };

    Console.ReadLine();
}

gateway

using var miHome = new MiHome("gateway password here"); // here we using developers api 

miHome.OnGateway += (_, gateway) =>
{
    gateway.EnableLight(); // by default this is "white" light
    Task.Delay(3000).Wait();
    gateway.DisableLight(); // light off
    Task.Delay(3000).Wait();
    gateway.EnableLight(255, 0, 0, 100); // turn on "red" light with full brightness 
    Task.Delay(3000).Wait();
    gateway.DisableLight(); // light off
    Task.Delay(3000).Wait();
    gateway.PlaySound(Gateway.Sound.IceWorldPiano, 50); // play ice world piano sound on gateway with volume 50%
    Task.Delay(3000).Wait();
    gateway.SoundsOff();
    gateway.PlayCustomSound(10_002, 50); // play custom sound with volume 50%
    Task.Delay(3000).Wait();
    gateway.SoundsOff();

};

Yes, it is possible to upload custom sounds to your gateway and use them in various scenarios. Check this instruction.

It is possible to add/remove/play custom radio channels in this version of gateway.

Bellow is a simple code snippet explaining how to use this feature.

var gw = new MiioGateway("192.168.1.12", "<your gateway token here>");

var radioChannels = gw.GetRadioChannels(); // get list of available custom radio channels

foreach (var channel in radioChannels)
{
    Console.WriteLine(channel);
}

gw.AddRadioChannel(1025, "http://192.168.1.1/my-playlist.m3u8"); // add custom radio channel
Task.Delay(1000).Wait();
gw.PlayRadio(1024, 50); // play newly-added channel with volume 50%
Task.Delay(1000).Wait();
gw.StopRadio(); // stop playing radio
Task.Delay(1000).Wait();
gw.RemoveRadioChannel(1024); // remove newly-added channel
Task.Delay(1000).Wait();
gw.RemoveAllRadioChannels(); // remove all custom radio channels

Async methods also supported.

Warning 1: Added radio channels are not persistant. Gateway may remove them from time to time. Warning 2: My gateway recognizes only songs in aac format (mp3 is not supported).

Here is minimal working sample of m3u8 file that gateway recognizes and respects.

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:240,
http://192.168.1.2/test.aac

EXT-X-MEDIA-SEQUENCE - number of songs in your playlist.

EXTINF - track length in seconds.

http://192.168.1.2/test.aac - url to your song

temperature_sensor

using var miHome = new MiHome();

miHome.OnThSensor += (_, thSensor) =>
{
    if (thSensor.Sid == "158d000182dfbc") // sid of specific device
    {
        Console.WriteLine(thSensor); // Sample output --> Temperature: 22,19°C, Humidity: 74,66%, Voltage: 3,035V

        thSensor.OnTemperatureChange += (_, e) =>
        {
            Console.WriteLine($"New temperature: {e.Temperature}");
        };

        thSensor.OnHumidityChange += (_, e) =>
        {
            Console.WriteLine($"New humidity: {e.Humidity}");
        };
    }
};

socket_plug

using var miHome = new MiHome();

miHome.OnSocketPlug += (_, socketPlug) =>
{
    if (socketPlug.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(socketPlug); // sample output Status: on, Inuse: 1, Load Power: 2.91V, Power Consumed: 37049W, Voltage: 3.6V

        socketPlug.TurnOff();
        Task.Delay(5000).Wait();
        socketPlug.TurnOn();
    }
};

motion_sensor motion_sensor_2

using var miHome = new MiHome();

//miHome.OnAqaraMotionSensor += (_, motionSensor) =>
miHome.OnMotionSensor += (_, motionSensor) =>
{
    if (motionSensor.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(motionSensor); // sample output Status: motion, Voltage: 3.035V, NoMotion: 0s

        motionSensor.OnMotion += (_, __) =>
        {
            Console.WriteLine($"{DateTime.Now}: Motion detected !");
        };

        motionSensor.OnNoMotion += (_, e) =>
        {
            Console.WriteLine($"{DateTime.Now}: No motion for {e.Seconds}s !");
        };
    }
};

door_window_sensor aqara_door_window_sensor

using var miHome = new MiHome();

//miHome.OnAqaraOpenCloseSensor += (_, windowSensor) =>
miHome.OnDoorWindowSensor += (_, windowSensor) =>
{
    if (windowSensor.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(windowSensor); // sample output Status: close, Voltage: 3.025V

        windowSensor.OnOpen += (_, __) =>
        {
            Console.WriteLine($"{DateTime.Now}: Window opened !");
        };

        windowSensor.OnClose += (_, __) =>
        {
            Console.WriteLine($"{DateTime.Now}: Window closed !");
        };

    }
};

water_sensor

using var miHome = new MiHome();

miHome.OnWaterLeakSensor += (_, waterLeakSensor) =>
{
    if (waterLeakSensor.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(waterLeakSensor); // Status: no_leak, Voltage: 3.015V

        waterLeakSensor.OnLeak += (_, __) =>
        {
            Console.WriteLine("Water leak detected !");
        };

        waterLeakSensor.OnNoLeak += (_, __) =>
        {
            Console.WriteLine("NO leak detected !");
        };

    }
};

smoke_sensor

using var miHome = new MiHome();

miHome.OnSmokeSensor += (_, smokeSensor) =>
{
    if (smokeSensor.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(smokeSensor); // sample output Alarm: off, Density: 0, Voltage: 3.075V

        smokeSensor.OnAlarm += (_, __) =>
        {
            Console.WriteLine("Smoke detected !");
        };

        smokeSensor.OnAlarmStopped += (_, __) =>
        {
            Console.WriteLine("Smoke alarm stopped");
        };

        smokeSensor.OnDensityChange += (_, e) =>
        {
            Console.WriteLine($"Density changed {e.Density}");
        };
    }
};

wireless dual wall switch

using var miHome = new MiHome();

miHome.OnWirelessDualWallSwitch += (_, wirelessDualSwitch) =>
{
    if (wirelessDualSwitch.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(wirelessDualSwitch);

        wirelessDualSwitch.OnLeftClick += (_) =>
        {
            Console.WriteLine("Left button clicked !");
        };

        wirelessDualSwitch.OnRightDoubleClick += (_) =>
        {
            Console.WriteLine("Right button double clicked !");
        };

        wirelessDualSwitch.OnLeftLongClick += (_) =>
        {
            Console.WriteLine("Left button long clicked !");
        };

    }
};

aqara_cube_sensor

using var miHome = new MiHome();

miHome.OnAqaraCubeSensor += (_, aqaraQube) =>
{
    if (aqaraQube.Sid == "158d00015dc6cc") // sid of specific device
    {
        Console.WriteLine(aqaraQube);

        aqaraQube.OnStatusChanged += (sender, eventArgs) =>
        {
            Console.WriteLine($"{sender} | {eventArgs.Status}");
        };

    }
};

humidifier

Before using the library you need to know IP and TOKEN of your air humidifier. If you don't know these parameters try to use the following code in order to discover air humidifiers in your LAN

AirHumidifier.OnDiscovered += (_, humidifier) =>
{
    Console.WriteLine($"ip: {humidifier.Ip}, token: {humidifier.Token}");
    // sample output ip: 192.168.1.5, token: 4a3a2f017b70097a850558c35c953b55
};

AirHumidifier.DiscoverDevices();

If your device hides his token follow these instructions in order to extract it.

Basic scenario

var airHumidifier = new AirHumidifier("<ip here>", "<token here>");
Console.WriteLine(airHumidifier);
/* sample output
Power: on
Mode: high
Temperature: 32.6 °C
Humidity: 34%
LED brightness: bright
Buzzer: on
Child lock: off
Target humidity: 50%
Model: zhimi.humidifier.v1
IP Address:192.168.1.5
Token: 4a3a2f017b70097a850558c35c953b55
*/

Functions

var airHumidifier = new AirHumidifier("<ip here>", "<token here>");
airHumidifier.PowerOn(); // power on
airHumidifier.PowerOff(); // power off
airHumidifier.SetMode(AirHumidifier.Mode.High); // set fan mode high/medium/low
airHumidifier.GetTemperature(); // get temperature
airHumidifier.GetHumidity(); // get humidity
airHumidifier.SetBrightness(AirHumidifier.Brightness.Bright); // set brighness bright/dim/off
airHumidifier.BuzzerOn(); // set buzzer sound on
airHumidifier.BuzzerOff(); // set buzzer sound off
airHumidifier.ChildLockOn(); // set child lock on
airHumidifier.ChildLockOff(); // set child lock oаа
airHumidifier.GetTargetHumidity(); // get humidity limit 20/30/40/50/60/70/80 %

Async versions of the operations above also supported.

mirobot

Before using the library you need to know IP and TOKEN of your Mi Robot.

If you don't know these parameters try to use the following code in order to discover mi robots in your LAN

MiRobotV1.OnDiscovered += (_, e) =>
{
	Console.WriteLine($"{e.Ip}, {e.Serial}, {e.Type}, {e.Token}");
};

MiRobotV1.DiscoverDevices()

If your device hides his token (you get 'ffffffffffffffffffffffffffffffff' instead of token) follow these instructions in order to extract it.

Supported methods

var miRobot = new MiRobotV1("<ip here>", "<token here>");
miRobot.Start(); // start the clean up
miRobot.Stop(); // stop the clean up
miRobot.Pause(); // pause the clean up
miRobot.Spot(); // start spot clean up
miRobot.Home(); // go back to the base station
miRobot.FindMe(); // tell the robot to give a voice

Async versions of the operations above also supported.

Warning: Mi Robot stores client requests in memory and doesn't allow to send request with the same client id twice.

It means that if you run the code snippet bellow twice.

var miRobot = new MiRobotV1("<ip here>", "<token here>");
miRobot.Start(); // start the clean up

The second attempt will fail. Work around is to set client id manually (usually increasing to 1 works)

var miRobot = new MiRobotV1("<ip here>", "<token here>", 2); // client request id is set to 2
miRobot.Start(); // start the clean up

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.