forked from calaos/calaos-homekit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
smart_shutter.go
146 lines (122 loc) · 4.52 KB
/
smart_shutter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"strconv"
"strings"
log "github.com/sirupsen/logrus"
"github.com/brutella/hap/accessory"
"github.com/brutella/hap/characteristic"
)
const (
CLOSING = iota
OPENING
STOPPED
)
type SmartShutter struct {
*accessory.WindowCovering
HoldPosition *characteristic.HoldPosition
Name *characteristic.Name
}
/*
TargetPosition :
This characteristic describes the target position of accessories.
This characteristic can be used with doors, windows, awnings or window coverings.
For windows and doors, a value of 0 indicates that a window (or door) is fully closed
while a value of 100 indicates a fully open position.
For blinds/shades/awnings, a value of 0 indicates a position that permits the least light
and a value of 100 indicates a position that allows most light.
*/
/*
CurrentPosition :
This characteristic describes the current position of accessories.
This characteristic can be used with doors, windows, awnings or window coverings.
For windows and doors, a value of 0 indicates that a window (or door) is fully closed
while a value of 100 indicates a fully open position.
For blinds/shades/awnings, a value of 0 indicates a position that permits the least light
and a value of 100 indicates a position that allows most light.
*/
/*
PositionState :
This characteristic describes the state of the position of accessories.
This characteristic can be used with doors, windows, awnings or window coverings for presentation purposes.
Format : uint8
Minimum value : 0
Maximum value : 2
Valid values :
0 : Going to the minimum value specified in metadata (closing)
1 : Going to the maximum value specified in metadata (opening)
2 : Stopped
3-255 : Reserved
*/
func NewSmartShutter(cio CalaosIO, id uint64) *SmartShutter {
acc := SmartShutter{}
info := accessory.Info{
Name: cio.Name,
SerialNumber: cio.ID,
Manufacturer: "Calaos",
Model: cio.IoType,
}
acc.WindowCovering = accessory.NewWindowCovering(info)
acc.WindowCovering.Id = id
acc.HoldPosition = characteristic.NewHoldPosition()
acc.Name = characteristic.NewName()
acc.WindowCovering.WindowCovering.AddC(acc.HoldPosition.C)
acc.WindowCovering.WindowCovering.AddC(acc.Name.C)
acc.Update(&cio)
acc.WindowCovering.WindowCovering.TargetPosition.OnValueRemoteUpdate(func(targetPosition int) {
//TODO: we should retrieve current position from cio object to compare, not from homekit
currentPosition := acc.WindowCovering.WindowCovering.CurrentPosition.Val
log.Debug("current position : ", currentPosition, " target position : ", targetPosition)
if targetPosition != currentPosition {
// calaos and homekit shutter position values are inverted
// calaos open = 0, closed = 100
// homekit open = 100, closed = 0
// we need to convert from homekit value to calaos with : 100 - x
state := "set " + strconv.Itoa(100-targetPosition)
log.Debug(state)
cio.State = state
CalaosUpdate(cio)
}
})
return &acc
}
func (acc *SmartShutter) Update(cio *CalaosIO) error {
if cio.GuiType == "shutter_smart" {
// split state to get current shutter position
words := strings.Fields(cio.State)
command := words[0]
value := words[len(words)-1]
ival, err := strconv.Atoi(value)
if err != nil {
return err
}
// calaos and homekit shutter position are inverted
// calaos open = 0, closed = 100
// homekit open = 100, closed = 0
// we need to convert from calaos value to homekit with : 100 - x
//TODO: target position should be retrieved from "set x" calaos command, but this target position is not sent from calaos server
// only the current position of the shutter is given by "up", "down" and "stop" and is sent every few milliseconds
val := 100 - ival
switch command {
case "up":
acc.WindowCovering.WindowCovering.PositionState.SetValue(OPENING)
acc.WindowCovering.WindowCovering.TargetPosition.SetValue(val)
acc.WindowCovering.WindowCovering.CurrentPosition.SetValue(val)
case "down":
acc.WindowCovering.WindowCovering.PositionState.SetValue(CLOSING)
acc.WindowCovering.WindowCovering.TargetPosition.SetValue(val)
acc.WindowCovering.WindowCovering.CurrentPosition.SetValue(val)
case "stop":
acc.WindowCovering.WindowCovering.TargetPosition.SetValue(val)
acc.WindowCovering.WindowCovering.CurrentPosition.SetValue(val)
acc.WindowCovering.WindowCovering.PositionState.SetValue(STOPPED)
acc.HoldPosition.SetValue(true)
case "calibration":
//TODO
default:
}
}
return nil
}
func (acc *SmartShutter) AccessoryGet() *accessory.A {
return acc.WindowCovering.A
}