Skip to content
3 changes: 2 additions & 1 deletion cli/cmd/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ const (
LogoutCmdName = "logout"
PingCmdName = "ping"
HomeAssistantCmdName = "ha"
ArgDoPeriodicRequests = "doPeriodicRequests"
ArgDoorStatusSupported = "doorStatusSupported"
ArgDevicePortsName = "devicePorts"
)
14 changes: 7 additions & 7 deletions cli/cmd/homeAssistant.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func init() {
mqttPassword string
mqttTelePeriod time.Duration
mqttTelePeriodFast time.Duration
devicePort int
doPeriodicRequests bool
devicePorts []int
doorStatusSupported bool
)

haCmd := &cobra.Command{
Expand All @@ -52,8 +52,8 @@ func init() {
mqttPassword = viper.GetString(ArgMqttPasswordName)
mqttTelePeriod = viper.GetDuration(ArgMqttTelePeriodName)
mqttTelePeriodFast = viper.GetDuration(ArgMqttTelePeriodFastName)
devicePort = viper.GetInt(ArgDevicePortName)
doPeriodicRequests = viper.GetBool(ArgDoPeriodicRequests)
devicePorts = viper.GetIntSlice(ArgDevicePortsName)
doorStatusSupported = viper.GetBool(ArgDoorStatusSupported)

mqttClientId := fmt.Sprintf("clientId_%s", deviceMac)

Expand All @@ -67,7 +67,7 @@ func init() {
cli.Log, localMac, mac, username, password, host, port, token,
mqttServerName, mqttClientId, mqttServerPort, mqttServerTls, mqttServerTlsValidaton,
mqttBaseTopic, mqttDeviceName, mqttUserName, mqttPassword, mqttTelePeriod, mqttTelePeriodFast,
byte(devicePort), doPeriodicRequests,
devicePorts, doorStatusSupported,
)
if err != nil {
cli.Log.Fatalf("%v", err)
Expand All @@ -93,8 +93,8 @@ func init() {
haCmd.Flags().StringVarP(&mqttDeviceName, ArgMqttDeviceNameName, "n", "garage", "Name of the local device in MQTT messages")
haCmd.Flags().DurationVarP(&mqttTelePeriod, ArgMqttTelePeriodName, "e", 15*time.Second, "Frequency of device state publish")
haCmd.Flags().DurationVarP(&mqttTelePeriodFast, ArgMqttTelePeriodFastName, "f", 5*time.Second, "Frequency of device state publish when door might be moving")
haCmd.Flags().IntVar(&devicePort, ArgDevicePortName, 0, "Port number of the door")
haCmd.Flags().BoolVar(&doPeriodicRequests, ArgDoPeriodicRequests, true, "Whether periodic status requests should be sent or not")
haCmd.Flags().IntSliceVar(&devicePorts, ArgDevicePortsName, []int{}, "Port numbers of the doors")
haCmd.Flags().BoolVar(&doorStatusSupported, ArgDoorStatusSupported, true, "Whether the controlled door supports door status (opening state) or not")
flag.Parse()
err := viper.BindPFlags(haCmd.Flags())
if err != nil {
Expand Down
53 changes: 32 additions & 21 deletions cli/homeAssistant/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ func (ha *HomeAssistanceMqttClient) forceReLogin() error {
return nil
}

func (ha *HomeAssistanceMqttClient) setStateMultiCall(count int) error {
return ha.setStateBisecurMultiCall(count)
func (ha *HomeAssistanceMqttClient) setStateMultiCall(count int, devicePort byte) error {
return ha.setStateBisecurMultiCall(count, devicePort)
//return mockDoor.SetStateMockMultiCall(count)
}

func (ha *HomeAssistanceMqttClient) setStateBisecurMultiCall(count int) error {
func (ha *HomeAssistanceMqttClient) setStateBisecurMultiCall(count int, devicePort byte) error {
const delayDuration = 1500 * time.Millisecond

for i := 0; i < count; i++ {
Expand All @@ -75,7 +75,7 @@ func (ha *HomeAssistanceMqttClient) setStateBisecurMultiCall(count int) error {
return fmt.Errorf("auto login failed. %v", err)
}

err = bisecur.SetState(ha.localMac, ha.deviceMac, ha.host, ha.port, ha.devicePort, ha.token)
err = bisecur.SetState(ha.localMac, ha.deviceMac, ha.host, ha.port, devicePort, ha.token)
if err != nil {
return fmt.Errorf("failed to get door status. %v", err)
}
Expand All @@ -88,34 +88,45 @@ func (ha *HomeAssistanceMqttClient) setStateBisecurMultiCall(count int) error {
return nil
}

func (ha *HomeAssistanceMqttClient) openDoor() error {
func (ha *HomeAssistanceMqttClient) impuls(devicePort byte) any {
ha.log.Info("Sending impuls...")

err := ha.setStateMultiCall(1, devicePort)
if err != nil {
return fmt.Errorf("failed to send impuls. %v", err)
}

return nil
}

func (ha *HomeAssistanceMqttClient) openDoor(devicePort byte) error {
ha.log.Info("Opening door...")

direction, position, err := ha.getDoorStatus()
direction, position, err := ha.getDoorStatus(devicePort)
if err != nil {
return fmt.Errorf("failed to get door status. %v", err)
}

switch direction {
case utils.CLOSING:
err := ha.setStateMultiCall(2)
err := ha.setStateMultiCall(2, devicePort)
if err != nil {
return fmt.Errorf("failed to set state. %v", err)
}
case utils.STOPPED, utils.OPEN, utils.CLOSED:
if position < 100 { // check if door is not already fully open
err := ha.setStateMultiCall(1)
err := ha.setStateMultiCall(1, devicePort)
if err != nil {
return fmt.Errorf("failed to set state. %v", err)
}

newDirection, _, err := ha.getDoorStatus()
newDirection, _, err := ha.getDoorStatus(devicePort)
if err != nil {
return fmt.Errorf("failed to get door status to confirm it is moving into the right direction. %v", err)
}

if newDirection != utils.OPENING && newDirection != utils.OPEN { // check if door needs to be reversed
err := ha.setStateMultiCall(2)
err := ha.setStateMultiCall(2, devicePort)
if err != nil {
return fmt.Errorf("failed to reverse moving direction. %v", err)
}
Expand All @@ -132,34 +143,34 @@ func (ha *HomeAssistanceMqttClient) openDoor() error {
return nil
}

func (ha *HomeAssistanceMqttClient) closeDoor() error {
func (ha *HomeAssistanceMqttClient) closeDoor(devicePort byte) error {
ha.log.Info("Closing door...")

direction, position, err := ha.getDoorStatus()
direction, position, err := ha.getDoorStatus(devicePort)
if err != nil {
return fmt.Errorf("failed to get door status. %v", err)
}

switch direction {
case utils.OPENING:
err := ha.setStateMultiCall(2) // stop then reverse
err := ha.setStateMultiCall(2, devicePort) // stop then reverse
if err != nil {
return fmt.Errorf("failed to set state. %v", err)
}
case utils.STOPPED, utils.OPEN:
if position > 0 { // check if door is not already fully closed
err := ha.setStateMultiCall(1)
err := ha.setStateMultiCall(1, devicePort)
if err != nil {
return fmt.Errorf("failed to set state. %v", err)
}

newDirection, _, err := ha.getDoorStatus()
newDirection, _, err := ha.getDoorStatus(devicePort)
if err != nil {
return fmt.Errorf("failed to get door status to confirm it is moving into the right direction. %v", err)
}

if newDirection != utils.CLOSING && newDirection != utils.CLOSED { // check if door needs to be reversed
err := ha.setStateMultiCall(2)
err := ha.setStateMultiCall(2, devicePort)
if err != nil {
return fmt.Errorf("failed to reverse moving direction. %v", err)
}
Expand All @@ -176,16 +187,16 @@ func (ha *HomeAssistanceMqttClient) closeDoor() error {
return nil
}

func (ha *HomeAssistanceMqttClient) stopDoor() error {
func (ha *HomeAssistanceMqttClient) stopDoor(devicePort byte) error {
ha.log.Infof("Stopping door...")

direction, _, err := ha.getDoorStatus()
direction, _, err := ha.getDoorStatus(devicePort)
if err != nil {
return fmt.Errorf("failed to get door status. %v", err)
}

if direction == utils.OPENING || direction == utils.CLOSING { // anything which means moving door
err := ha.setStateMultiCall(1)
err := ha.setStateMultiCall(1, devicePort)
if err != nil {
return fmt.Errorf("failed to stop the door. %v", err)
}
Expand All @@ -198,7 +209,7 @@ func (ha *HomeAssistanceMqttClient) stopDoor() error {
return nil
}

func (ha *HomeAssistanceMqttClient) getDoorStatus() (direction string, position int, err error) {
func (ha *HomeAssistanceMqttClient) getDoorStatus(devicePort byte) (direction string, position int, err error) {
/*
status="{\"StateInPercent\":0,\"DesiredStateInPercent\":0,\"ErrorResponse\":false,\"AutoClose\":false,\"DriveTime\":0,
\"Gk\":257,\"Hcp\":{\"PositionOpen\":false,\"PositionClose\":true,\"OptionRelais\":false,\"LightBarrier\":false,
Expand All @@ -218,7 +229,7 @@ func (ha *HomeAssistanceMqttClient) getDoorStatus() (direction string, position
var status *payload.HmGetTransitionResponse
err = utils.RetryAlways(utils.RetryCount, func() error {
var err2 error
status, err2 = bisecur.GetStatus(ha.localMac, ha.deviceMac, ha.host, ha.port, ha.devicePort, ha.token)
status, err2 = bisecur.GetStatus(ha.localMac, ha.deviceMac, ha.host, ha.port, devicePort, ha.token)

if err2.Error() == "PERMISSION_DENIED" { // TODO don't like string comparisons so should be refactored somehow while relogin also should be make more generic (think of other commands)
// Does it make sense to force relogin after a PERMISSION_DENIED error?
Expand Down
Loading