-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
fancl
committed
Mar 21, 2024
0 parents
commit edc3edb
Showing
17 changed files
with
2,411 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
bin/ | ||
|
||
.svn/ | ||
.godeps | ||
./build | ||
.cover/ | ||
dist | ||
_site | ||
_posts | ||
*.dat | ||
.vscode | ||
vendor | ||
|
||
# Go.gitignore | ||
|
||
# Compiled Object files, Static and Dynamic libs (Shared Objects) | ||
*.o | ||
*.a | ||
*.so | ||
|
||
# Folders | ||
_obj | ||
_test | ||
storage | ||
.idea | ||
|
||
# Architecture specific extensions/prefixes | ||
*.[568vq] | ||
[568vq].out | ||
|
||
*.cgo1.go | ||
*.cgo2.c | ||
_cgo_defun.c | ||
_cgo_gotypes.go | ||
_cgo_export.* | ||
|
||
_testmain.go | ||
|
||
*.exe | ||
*.local | ||
.DS_Store | ||
|
||
profile | ||
|
||
# vim stuff | ||
*.sw[op] | ||
|
||
|
||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
.vscode/* | ||
!.vscode/extensions.json | ||
|
||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Getting started | ||
|
||
Xiaomi IoT devices protocol | ||
|
||
# Usage | ||
|
||
### MiIO protocol | ||
|
||
#### Example | ||
|
||
```go | ||
|
||
device := miio.NewDevice("address","token") | ||
if err := device.Dial(context.Background());err != nil{ | ||
return | ||
} | ||
defer device.Close() | ||
|
||
if info,err := device.Info(context.Background());err == nil{ | ||
fmt.Println(info) | ||
} | ||
|
||
``` | ||
|
||
#### Method | ||
|
||
* **Info** Get device info | ||
* **GetAttributes** Get device props | ||
* **GetProperties** Get device properties | ||
* **SetProperties** Set device properties | ||
* **Action** Execute device action | ||
* **Execute** Execute command | ||
|
||
|
||
### Mi Cloud | ||
|
||
#### Example | ||
|
||
```go | ||
client := cloud.New("country","username","password") | ||
|
||
if err = client.Login(context.Background());err != nil { | ||
return | ||
} | ||
client.GetHomes(context.Background()) | ||
``` | ||
|
||
#### Method | ||
|
||
* **Login** Login Mi cloud | ||
* **GetHomes** Get mi homes | ||
* **GetHomeDevices** Get home devices | ||
* **GetDevices** Get all devices | ||
* **GetLastMessage** Get last messages | ||
* **GetSensorHistory** Get sensor histories | ||
* **GetDeviceProps** Get device properties, like `miio` `GetProperties` | ||
* **SetDeviceProps** Set device properties, like `miio` `SetProperties` | ||
* **ExecuteDeviceAction** Execute device action, like `miio` `Action` | ||
* **Request** do http request | ||
|
||
|
||
### Command | ||
|
||
build command | ||
|
||
```shell | ||
go build -o bin/miio cmd/main.go | ||
``` | ||
|
||
`miio` command help | ||
|
||
```shell | ||
$ miio --help | ||
|
||
miio an analog terminal that implements miio, capable of obtaining properties and sending instructions | ||
|
||
Usage: | ||
miio [command] | ||
|
||
Available Commands: | ||
action Do device action | ||
completion Generate the autocompletion script for the specified shell | ||
execute Execute device command | ||
get_properties Get device properties | ||
help Help about any command | ||
info Show device info | ||
parse_pcap Parse pcap filename | ||
set_properties Set device properties | ||
|
||
Flags: | ||
-h, --help help for miio | ||
--ip string device address | ||
--token string device token | ||
|
||
Use "miio [command] --help" for more information about a command. | ||
``` | ||
|
||
## Protocl | ||
|
||
Check full protocol specs [here](https://github.com/OpenMiHome/mihome-binary-protocol). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package miio | ||
|
||
import ( | ||
"bytes" | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/md5" | ||
"errors" | ||
) | ||
|
||
var ( | ||
ErrUnPadding = errors.New("UnPadding error") | ||
) | ||
|
||
type ( | ||
tokenCipher struct { | ||
Token []byte | ||
key []byte | ||
iv []byte | ||
} | ||
) | ||
|
||
func (c *tokenCipher) md5Sum(bs ...[]byte) []byte { | ||
hash := md5.New() | ||
for _, b := range bs { | ||
hash.Write(b) | ||
} | ||
return hash.Sum(nil) | ||
} | ||
|
||
func (c *tokenCipher) PKCS7Padding(src []byte, blockSize int) []byte { | ||
padding := blockSize - len(src)%blockSize | ||
buf := bytes.Repeat([]byte{byte(padding)}, padding) | ||
return append(src, buf...) | ||
} | ||
|
||
func (c *tokenCipher) PKCS7UnPadding(src []byte) ([]byte, error) { | ||
length := len(src) | ||
if length == 0 { | ||
return src, ErrUnPadding | ||
} | ||
buf := int(src[length-1]) | ||
if length < buf { | ||
return src, ErrUnPadding | ||
} | ||
return src[:(length - buf)], nil | ||
} | ||
|
||
func (c *tokenCipher) Encrypt(in []byte) (out []byte, err error) { | ||
var ( | ||
mode cipher.BlockMode | ||
block cipher.Block | ||
) | ||
if block, err = aes.NewCipher(c.key); err != nil { | ||
return | ||
} | ||
mode = cipher.NewCBCEncrypter(block, c.iv) | ||
in = c.PKCS7Padding(in, mode.BlockSize()) | ||
out = make([]byte, len(in)) | ||
mode.CryptBlocks(out, in) | ||
return | ||
} | ||
|
||
func (c *tokenCipher) Decrypt(in []byte) (out []byte, err error) { | ||
var ( | ||
mode cipher.BlockMode | ||
block cipher.Block | ||
) | ||
if block, err = aes.NewCipher(c.key); err != nil { | ||
return | ||
} | ||
out = make([]byte, len(in)) | ||
mode = cipher.NewCBCDecrypter(block, c.iv) | ||
mode.CryptBlocks(out, in) | ||
return c.PKCS7UnPadding(out) | ||
} | ||
|
||
func newTokenCipher(token []byte) *tokenCipher { | ||
c := &tokenCipher{ | ||
Token: make([]byte, len(token)), | ||
} | ||
copy(c.Token[:], token[:]) | ||
c.key = c.md5Sum(c.Token) | ||
c.iv = c.md5Sum(c.key, c.Token) | ||
return c | ||
} |
Oops, something went wrong.