mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-31 13:34:22 +02:00
[automower] Status update via Husqvarna WebSocket API (#18630)
* initial checkin: working WSS communication Signed-off-by: Michael Weger <weger.michael@gmx.net>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Automower Binding
|
||||
|
||||
This is the binding for [Husqvarna Automower® robotic lawn mowers](https://www.husqvarna.com/uk/products/robotic-lawn-mowers/).
|
||||
This binding allows you to integrate, view and control Automower® lawn mowers in the openHAB environment.
|
||||
This binding allows you to integrate, view and control Husqvarna Automower® lawn mowers in the openHAB environment.
|
||||
|
||||
## Supported Things
|
||||
|
||||
@@ -21,62 +21,73 @@ Once the bridge is created and configured, openHAB will automatically discover a
|
||||
|
||||
- appKey (mandatory): The Application Key is required to communicate with the Automower® Connect API. It can be obtained by registering an Application on [the Husqvarna Website](https://developer.husqvarnagroup.cloud/). This application also needs to be connected to the ["Authentication API" and the "Automower® Connect API"](https://developer.husqvarnagroup.cloud/docs/getting-started)
|
||||
- appSecret (mandatory): The Application Secret is required to communicate with the Automower® Connect API. It can be obtained by registering an Application on [the Husqvarna Website](https://developer.husqvarnagroup.cloud/).
|
||||
- pollingInterval (optional): How often the bridge state should be queried in seconds. Default is 1h (3600s)
|
||||
- pollingInterval (optional): How often the current Automower® states should be polled in seconds via REST API. Default is 5min (300s)
|
||||
|
||||
Keep in mind that the status of the bridge should not be queried too often.
|
||||
According to the Husqvarna documentation not more than 10000 requests per month / 1 request per second and application key are allowed.
|
||||
With the default value of 1h this would mean ~720 requests per month for the bridge state
|
||||
Keep in mind that the REST API should not be queried too frequently.
|
||||
According to Husqvarna's guidelines, each application key is limited to 10.000 requests per month and 1 request per second.
|
||||
|
||||
With the default polling interval of 5min, the bridge will make approximately 8.640 requests per month.
|
||||
As the states are polled from the `bridge`, the number does not scale with the number of `automower`.
|
||||
|
||||
In addition to periodic polling, the binding also receives event-triggered notifications whenever there are changes to the Automower®'s status, position, settings, or messages.
|
||||
|
||||
`automower:`
|
||||
|
||||
- mowerId (mandatory): The Id of an Automower® as used by the Automower® Connect Api to identify a mower. This is automatically filled when the thing is discovered
|
||||
- pollingInterval (optional): How often the current Automower® state should be polled in seconds. Default is 10min (600s)
|
||||
|
||||
Keep in mind that the status of the Automower® should not be queried too often.
|
||||
According to the Husqvarna documentation not more than 10000 requests per month / 1 request per second and application key are allowed.
|
||||
With the default value of 10min this would mean ~4300 requests per month per single Automower®
|
||||
- mowerId (mandatory): The Id of an Automower® as used by the Automower® Connect API to identify a Automower®. This is automatically filled when the thing is discovered
|
||||
- mowerZoneId (optional): Time zone of the Automower® (e.g. Europe/Berlin). Default is the time zone of the system
|
||||
|
||||
## Channels
|
||||
|
||||
### Status Channels
|
||||
|
||||
These channels represent the Automower® status.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|---------------------------------------|----------------------|-----|----------------------------------------------------------------------------------------------------------------|-------|
|
||||
| status#name | String | R | The name of the Automower® | false |
|
||||
| status#name | String | R | The name of the mower | false |
|
||||
| status#mode | String | R | The current mode (MAIN_AREA, SECONDARY_AREA, HOME, DEMO, UNKNOWN) | false |
|
||||
| status#activity | String | R | The current activity (UNKNOWN, NOT_APPLICABLE, MOWING, GOING_HOME, CHARGING, LEAVING, PARKED_IN_CS, STOPPED_IN_GARDEN) | false |
|
||||
| status#inactive-reason | String | R | The current reason for being inactive (NONE, PLANNING, SEARCHING_FOR_SATELLITES) | false |
|
||||
| status#state | String | R | The current state (UNKNOWN, NOT_APPLICABLE, PAUSED, IN_OPERATION, WAIT_UPDATING, WAIT_POWER_UP, RESTRICTED_NONE, RESTRICTED_WEEK_SCHEDULE, RESTRICTED_PARK_OVERRIDE, RESTRICTED_SENSOR, RESTRICTED_DAILY_LIMIT, RESTRICTED_FOTA, RESTRICTED_FROST, RESTRICTED_ALL_WORK_AREAS_COMPLETED, RESTRICTED_EXTERNAL, OFF, STOPPED, ERROR, FATAL_ERROR, ERROR_AT_POWER_UP) | false |
|
||||
| status#work-area-id<sup id="a1">[1](#f1)</sup> | Number | R | Id of the active work area | true |
|
||||
| status#work-area<sup id="a1">[1](#f1)</sup> | String | R | Name of the active work area | false |
|
||||
| status#last-update | DateTime | R | The time when the Automower® updated its states | false |
|
||||
| status#work-area-id<sup id="a1">[1](#f1)</sup> | Number | R | Id of the active Work Area | true |
|
||||
| status#work-area<sup id="a1">[1](#f1)</sup> | String | R | Name of the active Work Area | false |
|
||||
| status#last-update | DateTime | R | The time when the mower sent the last update | false |
|
||||
| status#last-poll-update | DateTime | R | The time when the binding polled the last update from the cloud | true |
|
||||
| status#poll-update | Switch | R | Poll Automower® status update from the cloud | true |
|
||||
| status#poll-update | Switch | R/W | Poll mower status update from the cloud (`sendCommand(ON)`) | true |
|
||||
| status#battery | Number:Dimensionless | R | The battery state of charge in percent | false |
|
||||
| status#error-code | Number | R/W | The current error code. `sendCommand(0)` to confirm current non fatal error | true |
|
||||
| status#error-message | String | R | The current error message | false |
|
||||
| status#error-timestamp | DateTime | R | The timestamp when the current error occurred | false |
|
||||
| status#error-confirmable<sup id="a1">[1](#f1)</sup> | Switch | R | If the mower has an Error Code this attribute states if the error is confirmable | true |
|
||||
| status#next-start | DateTime | R | The time for the next auto start. If the mower is charging then the value is the estimated time when it will be leaving the charging station. If the mower is about to start now, the value is NULL | false |
|
||||
| status#override-action | String | R | The action that overrides current planner operation | true |
|
||||
| status#restricted-reason | String | R | A reason that restrics current planner operation (NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST, ALL_WORK_AREAS_COMPLETED, EXTERNAL) | false |
|
||||
| status#external-reason | String | R | An external reason set by i.e. IFTTT, Google Assistant or Amazon Alexa that restrics current planner operation | true |
|
||||
| status#error-confirmable<sup id="a1">[1](#f1)</sup> | Switch | R | If the mower has an error, this attribute states if the error is confirmable | true |
|
||||
| status#next-start | DateTime | R | The time for the next scheduled start. If the mower is charging then the value is the estimated time when it will leave the charging station. If the mower is about to start now, the value is NULL | false |
|
||||
| status#override-action | String | R | The action that overrides the current planner operation | true |
|
||||
| status#restricted-reason | String | R | The reason that restrics the current planner operation (NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST, ALL_WORK_AREAS_COMPLETED, EXTERNAL) | false |
|
||||
| status#external-reason | String | R | An external reason set by i.e. Google Assistant or Amazon Alexa that restrics the current planner operation | true |
|
||||
| status#position | Location | R | Last GPS Position of the mower | false |
|
||||
|
||||
### Settings Channels
|
||||
|
||||
These channels hold Automower® settings.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|---------------------------------------------------|--------|-------------|-------------------------------------------------------------------------|----------|
|
||||
| setting#cutting-height | Number | R/W | Prescaled cutting height, Range: 1-9 | false |
|
||||
| setting#headlight-mode<sup id="a1">[1](#f1)</sup> | String | R/W | Headlight Mode (ALWAYS_ON, ALWAYS_OFF, EVENING_ONLY, EVENING_AND_NIGHT) | false |
|
||||
|
||||
The absolute cutting height can be calculated from the prescaled cutting height using the following formula:
|
||||
|
||||
`cuttingHeightInCM = round((minCuttingHeight + ((maxCuttingHeight - minCuttingHeight) * (setting#cutting-height - 1) / 8)) * 2) / 2`
|
||||
|
||||
### Statistics Channels
|
||||
|
||||
These channels hold different Automower® statistics.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-------------------------------------|----------------------|-------------|---------------------------------------------------------------------------------------------|----------|
|
||||
| statistic#cutting-blade-usage-time | Number:Time | R/W | The time since the last reset of the cutting blade usage counter. `sendCommand(0)` to reset | false |
|
||||
| statistic#down-time | Number:Time | R | The time the mower has been disconnected from the cloud | true |
|
||||
| statistic#number-of-charging-cycles | Number | R | Number of charging cycles | false |
|
||||
| statistic#number-of-collisions | Number | R | The total number of collisions | false |
|
||||
| statistic#number-of-collisions | Number | R | Total number of collisions | false |
|
||||
| statistic#total-charging-time | Number:Time | R | Total charging time | false |
|
||||
| statistic#total-cutting-time | Number:Time | R | Total Cutting Time | false |
|
||||
| statistic#total-cutting-percent | Number:Dimensionless | R | Total cutting time in percent | false |
|
||||
@@ -106,19 +117,6 @@ These channels hold the different Calendar Task configurations.
|
||||
|
||||
\<x\> ... 01-#calendartasks
|
||||
|
||||
### Position Channels
|
||||
|
||||
These channels hold the last 50 GPS positions recorded by the Automower®, thus describing the path it followed.
|
||||
Position 01 is the latest recorded position, the other positions are pushed back, thus removing the previous position 50 from the list because it is replaced by the previous position 49.
|
||||
Channel `last-position` is always identical with channel `position01` and thus provides more convenient access if only the latest GPS information is required by the user.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------------------------------|----------|-------------|---------------------------------------------------------|----------|
|
||||
| position#last<sup id="a1">[1](#f1)</sup> | Location | R | Last GPS Position (identical with positions#position01) | false |
|
||||
| position#\<x\>-pos<sup id="a1">[1](#f1)</sup> | Location | R | GPS Position \<x\> | true |
|
||||
|
||||
\<x\> ... 01-50
|
||||
|
||||
### Stayout Zones Channels
|
||||
|
||||
These channels hold the different Stayout Zone configurations.
|
||||
@@ -126,9 +124,9 @@ These channels hold the different Stayout Zone configurations.
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------------------------------------------|--------|-------------|------------------------------------------------------------------------------------------------------------------------------------|----------|
|
||||
| stayoutzone#dirty<sup id="a1">[1](#f1)</sup> | Switch | R | If the stay-out zones are synchronized with the Husqvarna cloud. If the map is dirty you can not enable or disable a stay-out zone | true |
|
||||
| stayoutzone#\<x\>-zone-id<sup id="a1">[1](#f1)</sup> | String | R | Id of the Stayout zone | true |
|
||||
| stayoutzone#\<x\>-zone-name<sup id="a1">[1](#f1)</sup> | String | R | The name of the Stayout zone | true |
|
||||
| stayoutzone#\<x\>-zone-enabled<sup id="a1">[1](#f1)</sup> | Switch | R/W | If the Stayout zone is enabled, the Automower® will not access the zone | true |
|
||||
| stayoutzone#\<x\>-zone-id<sup id="a1">[1](#f1)</sup> | String | R | Id of the stay-out zone | true |
|
||||
| stayoutzone#\<x\>-zone-name<sup id="a1">[1](#f1)</sup> | String | R | The name of the stay-out zone | true |
|
||||
| stayoutzone#\<x\>-zone-enabled<sup id="a1">[1](#f1)</sup> | Switch | R/W | If the stay-out zone is enabled, the mower will not access the zone | true |
|
||||
|
||||
\<x\> ... 01-#stayoutzones
|
||||
|
||||
@@ -139,69 +137,68 @@ These channels hold the different Work Area configurations.
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------------------------------------------------------------------------------------------|-----------------------|-------------|-----------------------------------------------------|----------|
|
||||
| workarea#\<x\>-area-id<sup id="a1">[1](#f1)</sup> | Number | R | Id of the Work Area | false |
|
||||
| workarea#\<x\>-area-name<sup id="a1">[1](#f1)</sup> | String | R | Name of the work area | false |
|
||||
| workarea#\<x\>-area-cutting-height<sup id="a1">[1](#f1)</sup> | Number:Dimensionless | R/W | Cutting height in percent. 0-100 | false |
|
||||
| workarea#\<x\>-area-enabled<sup id="a1">[1](#f1)</sup> | Switch | R/W | If the work area is enabled or disabled | false |
|
||||
| workarea#\<x\>-area-progress<sup id="a1">[1](#f1)</sup><sup>,</sup><sup id="a2">[2](#f2)</sup> | Number | R | The progress on a work area | true |
|
||||
| workarea#\<x\>-area-last-time-completed<sup id="a1">[1](#f1)</sup><sup>,</sup><sup id="a2">[2](#f2)</sup> | DateTime | R | Timestamp when the work area was last completed | true |
|
||||
| workarea#\<x\>-area-name<sup id="a1">[1](#f1)</sup> | String | R | Name of the Work Area | false |
|
||||
| workarea#\<x\>-area-cutting-height<sup id="a1">[1](#f1)</sup> | Number:Dimensionless | R/W | Cutting height of the Work Area in percent. 0-100 | false |
|
||||
| workarea#\<x\>-area-enabled<sup id="a1">[1](#f1)</sup> | Switch | R/W | If the Work Area is enabled or disabled | false |
|
||||
| workarea#\<x\>-area-progress<sup id="a1">[1](#f1)</sup><sup>,</sup><sup id="a2">[2](#f2)</sup> | Number | R | The progress on a Work Area | true |
|
||||
| workarea#\<x\>-area-last-time-completed<sup id="a1">[1](#f1)</sup><sup>,</sup><sup id="a2">[2](#f2)</sup> | DateTime | R | Timestamp when the Work Area was last completed | true |
|
||||
|
||||
\<x\> ... 01-#workareas
|
||||
|
||||
### Messages
|
||||
|
||||
These channels hold the last 50 messages recorded by the Automower®.
|
||||
Message 01 is the latest recorded message, the other messages are pushed back, thus removing the previous message 50 from the list because it is replaced by the previous message 49.
|
||||
These channels hold the last message recorded by the Automower®.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-------------------------|----------|-------------|------------------------------------------|----------|
|
||||
| message#\<x\>-time | DateTime | R | Timestamp when the event occurred | true |
|
||||
| message#\<x\>-code | Number | R | (Error) code of the event | true |
|
||||
| message#\<x\>-text | String | R | The message | true |
|
||||
| message#\<x\>-severity | String | R | The severity of the event | true |
|
||||
| message#\<x\>-position | Location | R | GPS Position of the event (if available) | true |
|
||||
|
||||
\<x\> ... 01-50
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------|----------|-------------|-----------------------------------------------|----------|
|
||||
| message#msg-timestamp | DateTime | R | The time when the last error occurred | true |
|
||||
| message#msg-code | Number | R | The last error code | true |
|
||||
| message#msg-text | String | R | The last error message | true |
|
||||
| message#msg-severity | String | R | The severity of the last error | true |
|
||||
| message#msg-position | Location | R | GPS position of the last event (if available) | true |
|
||||
|
||||
### Command Channels
|
||||
|
||||
Command channels that trigger actions.
|
||||
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------------------|----------|-------------|------------------------------------------|----------|
|
||||
| command#start | Number | W | Start the Automower® for a duration | false |
|
||||
| command#resume_schedule | Switch | W | Resume the Automower® schedule | false |
|
||||
| command#pause | Switch | W | Pause the Automower® | false |
|
||||
| command#park | Number | W | Park the Automower® for a duration | false |
|
||||
| command#park_until_next_schedule | Switch | W | Park the Automower® until next schedule | false |
|
||||
| command#park_until_further_notice | Switch | W | Park the Automower® until further notice | false |
|
||||
| channel | type | access mode | description | advanced |
|
||||
|-----------------------------------|----------|-------------|--------------------------------------------------------------------------------------------------------|----------|
|
||||
| command#start | Number | W | Start the mower for the given duration, overriding the schedule | false |
|
||||
| command#start_in_workarea | Number | W | Start the mower in the given Work Area, overriding the schedule. The mower will continue forever | false |
|
||||
| command#resume_schedule | Switch | W | Resume the schedule of the mower | false |
|
||||
| command#pause | Switch | W | Pause the mower at the current location until manual resume | false |
|
||||
| command#park | Number | W | Park the mower for the given duration, overriding the schedule | false |
|
||||
| command#park_until_next_schedule | Switch | W | Park the mower, fully charge it and start afterwards according to the schedule | false |
|
||||
| command#park_until_further_notice | Switch | W | Park the mower until it is started again by the start action/command or the schedule gets resumed | false |
|
||||
|
||||
## Actions
|
||||
|
||||
The following actions are available for `automower` things:
|
||||
|
||||
| action name | arguments | description |
|
||||
|----------------------------|------------------|------------------------------------------------------------------------------------------------|
|
||||
| start | `duration (int)` | Start the Automower® for the given duration (minutes), overriding the schedule |
|
||||
| pause | - | Pause the Automower® wherever it is currently located |
|
||||
| parkUntilNextSchedule | - | Park the Automower®, fully charges it and starts afterwards according to the schedule |
|
||||
| parkUntilFurtherNotice | - | Park the Automower® until it is started again by the start action or the schedule gets resumed |
|
||||
| park | `duration (int)` | Park the Automower® for the given duration (minutes), overriding the schedule |
|
||||
| resumeSchedule | - | Resume the schedule for the Automower® |
|
||||
| confirmError | - | Confirm current non fatal error |
|
||||
| resetCuttingBladeUsageTime | - | Reset the cutting blade usage time |
|
||||
| setSettings | `byte cuttingHeight`<br/>`String headlightMode` | Update Automower® settings |
|
||||
| setWorkArea | `long workAreaId`<br/>`boolean enable`<br/>`byte cuttingHeight` | Update work area settings |
|
||||
| setStayOutZone | `String zoneId`<br/>`boolean enable` | Enable or disable stay-out zone |
|
||||
| setCalendarTask | `Long workAreaId` (optional, set to `null` if the mower doesn't support work areas)<br/>`short[] start`<br/>`short[] duration`<br/>`boolean[] monday`<br/>`boolean[] tuesday`<br/>`boolean[] wednesday`<br/>`boolean[] thursday`<br/>`boolean[] friday`<br/>`boolean[] saturday`<br/>`boolean[] sunday` | Update calendar task settings. Parameter are an array for all calendar tasks (per work area) |
|
||||
| poll | - | Poll Automower® status update from the cloud |
|
||||
| action name | arguments | description |
|
||||
|----------------------------|-------------------|--------------------------------------------------------------------------------------------------------|
|
||||
| start | `duration (long)` | Start the mower for the given duration (minutes), overriding the schedule |
|
||||
| startInWorkArea | `workAreaId (long)`<br/>`duration (long)` | Start the mower in the given Work Area for the given duration (minutes), overriding the schedule. If duration is skipped the mower will continue forever |
|
||||
| pause | - | Pause the mower at the current location until manual resume |
|
||||
| park | `duration (long)` | Park the mower for the given duration (minutes), overriding the schedule |
|
||||
| parkUntilNextSchedule | - | Park the mower, fully charge it and start afterwards according to the schedule |
|
||||
| parkUntilFurtherNotice | - | Park the mower until it is started again by the start action/command or the schedule gets resumed |
|
||||
| resumeSchedule | - | Resume the schedule of the mower |
|
||||
| confirmError | - | Confirm current non fatal error |
|
||||
| resetCuttingBladeUsageTime | - | Reset the cutting blade usage time |
|
||||
| setSettings | `byte cuttingHeight`<br/>`String headlightMode` | Update mower settings |
|
||||
| setWorkArea | `long workAreaId`<br/>`boolean enable`<br/>`byte cuttingHeight` | Update Work Area settings |
|
||||
| setStayOutZone | `String zoneId`<br/>`boolean enable` | Enable or disable stay-out zone |
|
||||
| setCalendarTask | `Long workAreaId` (optional, set to `null` if the mower doesn't support Work Areas)<br/>`short[] start`<br/>`short[] duration`<br/>`boolean[] monday`<br/>`boolean[] tuesday`<br/>`boolean[] wednesday`<br/>`boolean[] thursday`<br/>`boolean[] friday`<br/>`boolean[] saturday`<br/>`boolean[] sunday` | Update calendar task settings. Parameter are an array for all calendar tasks (per Work Area) |
|
||||
| poll | - | Poll mower status update from the cloud |
|
||||
|
||||
## Full Example
|
||||
|
||||
### automower.thing
|
||||
|
||||
```java
|
||||
Bridge automower:bridge:mybridge [ appKey="<your_private_application_key>", userName="<your_username>", password="<your_password>" ] {
|
||||
Thing automower myAutomower [ mowerId="<your_id_received_from_discovery>", pollingInterval=3600 ] {
|
||||
Bridge automower:bridge:mybridge [ appKey="<your_private_application_key>", appSecret="<your_private_application_secret>", pollingInterval=300 ] {
|
||||
Thing automower 12345678-1234-12ab-1234-123456abcdef [ mowerId="12345678-1234-12ab-1234-123456abcdef" ] { // 1234... is an example of the id recieved via discovery
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -209,24 +206,23 @@ Bridge automower:bridge:mybridge [ appKey="<your_private_application_key>", user
|
||||
### automower.items
|
||||
|
||||
```java
|
||||
String Automower_Mode "Mode [%s]" { channel="automower:automower:mybridge:myAutomower:status#mode" }
|
||||
String Automower_Activity "Activity [%s]" { channel="automower:automower:mybridge:myAutomower:status#activity" }
|
||||
String Automower_State "State [%s]" { channel="automower:automower:mybridge:myAutomower:status#state" }
|
||||
DateTime Automower_Last_Update "Last Update" { channel="automower:automower:mybridge:myAutomower:status#last-update" }
|
||||
Number Automower_Battery "Battery [%d %%]" { channel="automower:automower:mybridge:myAutomower:status#battery" }
|
||||
Number Automower_Error_Code "Error Code [%d]" { channel="automower:automower:mybridge:myAutomower:status#error-code" }
|
||||
DateTime Automower_Error_Time "Error Time" { channel="automower:automower:mybridge:myAutomower:status#error-timestamp" }
|
||||
String Automower_Override_Action "Override Action [%s]" { channel="automower:automower:mybridge:myAutomower:status#override-action" }
|
||||
DateTime Automower_Next_Start_Time "Next Start Time" { channel="automower:automower:mybridge:myAutomower:status#next-start" }
|
||||
String Automower_Mode "Mode [%s]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#mode" }
|
||||
String Automower_Activity "Activity [%s]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#activity" }
|
||||
String Automower_State "State [%s]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#state" }
|
||||
DateTime Automower_Last_Update "Last Update" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#last-update" }
|
||||
Number Automower_Battery "Battery [%d %%]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#battery" }
|
||||
Number Automower_Error_Code "Error Code [%d]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#error-code" }
|
||||
DateTime Automower_Error_Time "Error Time" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#error-timestamp" }
|
||||
String Automower_Override_Action "Override Action [%s]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#override-action" }
|
||||
DateTime Automower_Next_Start_Time "Next Start Time" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#next-start" }
|
||||
Location Automower_Position "Last Position" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:status#position" }
|
||||
|
||||
Number Automower_Command_Start "Start mowing for duration [%d min]" { channel="automower:automower:mybridge:myAutomower:command#start" }
|
||||
Switch Automower_Command_Resume "Resume the schedule" { channel="automower:automower:mybridge:myAutomower:command#resume_schedule" }
|
||||
Switch Automower_Command_Pause "Pause the automower" { channel="automower:automower:mybridge:myAutomower:command#pause" }
|
||||
Number Automower_Command_Park "Park for duration [%d min]" { channel="automower:automower:mybridge:myAutomower:command#park" }
|
||||
Switch Automower_Command_Park_Next_Schedule "Park until next schedule" { channel="automower:automower:mybridge:myAutomower:command#park_until_next_schedule" }
|
||||
Switch Automower_Command_Park_Notice "Park until further notice" { channel="automower:automower:mybridge:myAutomower:command#park_until_further_notice" }
|
||||
|
||||
Location Automower_Last_Position "Last Position" { channel="automower:automower:mybridge:myAutomower:position#last-position" }
|
||||
Number Automower_Command_Start "Start mowing for duration [%d min]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#start" }
|
||||
Switch Automower_Command_Resume "Resume the schedule" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#resume_schedule" }
|
||||
Switch Automower_Command_Pause "Pause the automower" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#pause" }
|
||||
Number Automower_Command_Park "Park for duration [%d min]" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#park" }
|
||||
Switch Automower_Command_Park_Next_Schedule "Park until next schedule" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#park_until_next_schedule" }
|
||||
Switch Automower_Command_Park_Notice "Park until further notice" { channel="automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef:command#park_until_further_notice" }
|
||||
```
|
||||
|
||||
### automower.sitemap
|
||||
@@ -244,7 +240,7 @@ sitemap demo label="Automower"
|
||||
Text item=Automower_Error_Time
|
||||
Text item=Automower_Override_Action
|
||||
Text item=Automower_Next_Start_Time
|
||||
Text item=Automower_Calendar_Tasks
|
||||
Text item=Automower_Position
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -262,7 +258,7 @@ then
|
||||
Automower_Command_Park_Notice.sendCommand(ON)
|
||||
|
||||
// alternative via actions
|
||||
val mowerActions = getActions("automower", "automower:automower:mybridge:myAutomower")
|
||||
val mowerActions = getActions("automower", "automower:automower:mybridge:12345678-1234-12ab-1234-123456abcdef")
|
||||
mowerActions.parkUntilFurtherNotice()
|
||||
end
|
||||
```
|
||||
@@ -270,4 +266,4 @@ end
|
||||
## Footnotes
|
||||
|
||||
- <b id="f1">1)</b> ... Channel availability depends on Automower® capabilities [↩](#a1)
|
||||
- <b id="f2">2)</b> ... Channel available for EPOS Automower® and systematic mowing work areas only [↩](#a2)
|
||||
- <b id="f2">2)</b> ... Channel available for EPOS Automower® and systematic mowing Work Area only [↩](#a2)
|
||||
|
||||
+10
-16
@@ -59,6 +59,7 @@ public class AutomowerBindingConstants {
|
||||
public static final String CHANNEL_STATUS_OVERRIDE_ACTION = GROUP_STATUS + "override-action";
|
||||
public static final String CHANNEL_STATUS_RESTRICTED_REASON = GROUP_STATUS + "restricted-reason";
|
||||
public static final String CHANNEL_STATUS_EXTERNAL_REASON = GROUP_STATUS + "external-reason";
|
||||
public static final String CHANNEL_STATUS_POSITION = GROUP_STATUS + "position";
|
||||
|
||||
// List of all setting Channel ids
|
||||
public static final String GROUP_SETTING = "setting#";
|
||||
@@ -118,12 +119,6 @@ public class AutomowerBindingConstants {
|
||||
new ChannelTypeUID(BINDING_ID, "calendarTaskWorkAreaIdType"),
|
||||
new ChannelTypeUID(BINDING_ID, "workareaNameType")));
|
||||
|
||||
// Position Channel ids
|
||||
public static final String GROUP_POSITION = "position#";
|
||||
|
||||
public static final String CHANNEL_POSITION_LAST = GROUP_POSITION + "last";
|
||||
public static final String CHANNEL_POSITION = "pos";
|
||||
|
||||
// Stayout Zones Channel ids
|
||||
public static final String GROUP_STAYOUTZONE = "stayoutzone#";
|
||||
|
||||
@@ -154,18 +149,17 @@ public class AutomowerBindingConstants {
|
||||
// Messages Channel ids
|
||||
public static final String GROUP_MESSAGE = "message#";
|
||||
|
||||
public static final ArrayList<String> CHANNEL_MESSAGE = new ArrayList<>(
|
||||
List.of("msg-timestamp", "msg-code", "msg-text", "msg-severity", "msg-gps-position"));
|
||||
|
||||
public static final ArrayList<ChannelTypeUID> CHANNEL_TYPE_MESSAGE = new ArrayList<>(List.of(
|
||||
new ChannelTypeUID(BINDING_ID, "messageTimeType"), new ChannelTypeUID(BINDING_ID, "messageCodeType"),
|
||||
new ChannelTypeUID(BINDING_ID, "messageType"), new ChannelTypeUID(BINDING_ID, "messageSeverityType"),
|
||||
new ChannelTypeUID(BINDING_ID, "messagePositionType")));
|
||||
public static final String CHANNEL_MESSAGE_TIMESTAMP = GROUP_MESSAGE + "msg-timestamp";
|
||||
public static final String CHANNEL_MESSAGE_CODE = GROUP_MESSAGE + "msg-code";
|
||||
public static final String CHANNEL_MESSAGE_TEXT = GROUP_MESSAGE + "msg-text";
|
||||
public static final String CHANNEL_MESSAGE_SEVERITY = GROUP_MESSAGE + "msg-severity";
|
||||
public static final String CHANNEL_MESSAGE_GPS_POSITION = GROUP_MESSAGE + "msg-gps-position";
|
||||
|
||||
// Command Channel ids
|
||||
public static final String GROUP_COMMAND = "command#";
|
||||
|
||||
public static final String CHANNEL_COMMAND_START = GROUP_COMMAND + "start";
|
||||
public static final String CHANNEL_COMMAND_START_IN_WORK_AREA = GROUP_COMMAND + "start_in_work_area";
|
||||
public static final String CHANNEL_COMMAND_RESUME_SCHEDULE = GROUP_COMMAND + "resume_schedule";
|
||||
public static final String CHANNEL_COMMAND_PAUSE = GROUP_COMMAND + "pause";
|
||||
public static final String CHANNEL_COMMAND_PARK = GROUP_COMMAND + "park";
|
||||
@@ -189,15 +183,15 @@ public class AutomowerBindingConstants {
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_STATUS_WORK_AREA = new ChannelTypeUID(BINDING_ID, "workAreaType");
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_STATUS_ERROR_CONFIRMABLE = new ChannelTypeUID(BINDING_ID,
|
||||
"errorConfirmableType");
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_STATUS_POSITION = new ChannelTypeUID(BINDING_ID, "positionType");
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_SETTING_HEADLIGHT_MODE = new ChannelTypeUID(BINDING_ID,
|
||||
"settingHeadlightModeType");
|
||||
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_POSITION_LAST = new ChannelTypeUID(BINDING_ID, "lastPositionType");
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_POSITION = new ChannelTypeUID(BINDING_ID, "positionType");
|
||||
public static final ChannelTypeUID CHANNEL_TYPE_STAYOUTZONES_DIRTY = new ChannelTypeUID(BINDING_ID,
|
||||
"zoneDirtyType");
|
||||
|
||||
public static final Map<Integer, String> ERROR = new HashMap<>() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
{
|
||||
put(0, "No message");
|
||||
put(1, "Outside working area");
|
||||
@@ -278,7 +272,7 @@ public class AutomowerBindingConstants {
|
||||
put(76, "Connection NOT changed");
|
||||
put(77, "Com board not available");
|
||||
put(78, "Slipped - Mower has Slipped. Situation not solved with moving pattern");
|
||||
put(79, "Invalid battery combination - Invalid combination of different battery types.");
|
||||
put(79, "Invalid battery combination - Invalid combination of different battery types");
|
||||
put(80, "Cutting system imbalance Warning");
|
||||
put(81, "Safety function faulty");
|
||||
put(82, "Wheel motor blocked, rear right");
|
||||
|
||||
+7
-3
@@ -29,6 +29,7 @@ import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.io.net.http.WebSocketFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
@@ -57,13 +58,15 @@ public class AutomowerHandlerFactory extends BaseThingHandlerFactory {
|
||||
protected final @NonNullByDefault({}) HttpClient httpClient;
|
||||
private @Nullable ServiceRegistration<?> automowerDiscoveryServiceRegistration;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final WebSocketFactory webSocketFactory;
|
||||
|
||||
@Activate
|
||||
public AutomowerHandlerFactory(@Reference OAuthFactory oAuthFactory, @Reference HttpClientFactory httpClientFactory,
|
||||
@Reference TimeZoneProvider timeZoneProvider) {
|
||||
@Reference TimeZoneProvider timeZoneProvider, @Reference WebSocketFactory webSocketFactory) {
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.webSocketFactory = webSocketFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,7 +77,8 @@ public class AutomowerHandlerFactory extends BaseThingHandlerFactory {
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
if (AutomowerBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
AutomowerBridgeHandler handler = new AutomowerBridgeHandler((Bridge) thing, oAuthFactory, httpClient);
|
||||
AutomowerBridgeHandler handler = new AutomowerBridgeHandler((Bridge) thing, oAuthFactory, httpClient,
|
||||
webSocketFactory.getCommonWebSocketClient());
|
||||
registerAutomowerDiscoveryService(handler);
|
||||
return handler;
|
||||
}
|
||||
@@ -89,8 +93,8 @@ public class AutomowerHandlerFactory extends BaseThingHandlerFactory {
|
||||
@Override
|
||||
protected synchronized void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof AutomowerBridgeHandler) {
|
||||
ServiceRegistration<?> automowerDiscoveryServiceRegistration = this.automowerDiscoveryServiceRegistration;
|
||||
if (automowerDiscoveryServiceRegistration != null) {
|
||||
// remove discovery service, if bridge handler is removed
|
||||
automowerDiscoveryServiceRegistration.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
+22
-6
@@ -49,7 +49,7 @@ public class AutomowerActions implements ThingActions {
|
||||
|
||||
@RuleAction(label = "@text/action-start-label", description = "@text/action-start-desc")
|
||||
public void start(
|
||||
@ActionInput(name = "duration", label = "@text/action-input-duration-label", description = "@text/action-input-duration-desc") int durationMin) {
|
||||
@ActionInput(name = "duration-min", label = "@text/action-input-duration-min-label", description = "@text/action-input-duration-min-desc") long durationMin) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
@@ -58,10 +58,26 @@ public class AutomowerActions implements ThingActions {
|
||||
}
|
||||
}
|
||||
|
||||
public static void start(ThingActions actions, int durationMin) {
|
||||
public static void start(ThingActions actions, long durationMin) {
|
||||
((AutomowerActions) actions).start(durationMin);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/action-start-in-work-area-label", description = "@text/action-start-in-work-area-desc")
|
||||
public void startInWorkArea(
|
||||
@ActionInput(name = "work-area-id", label = "@text/action-input-work-area-id-label", description = "@text/action-input-work-area-id-desc") long workAreaId,
|
||||
@ActionInput(name = "duration-min-opt", label = "@text/action-input-duration-min-opt-label", description = "@text/action-input-duration-min-opt-desc") @Nullable Long durationMin) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
} else {
|
||||
automowerHandler.sendAutomowerCommand(AutomowerCommand.START_IN_WORK_AREA, workAreaId, durationMin);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startInWorkArea(ThingActions actions, long workAreaId, @Nullable Long durationMin) {
|
||||
((AutomowerActions) actions).startInWorkArea(workAreaId, durationMin);
|
||||
}
|
||||
|
||||
@RuleAction(label = "@text/action-pause-label", description = "@text/action-pause-desc")
|
||||
public void pause() {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
@@ -106,7 +122,7 @@ public class AutomowerActions implements ThingActions {
|
||||
|
||||
@RuleAction(label = "@text/action-park-label", description = "@text/action-park-desc")
|
||||
public void park(
|
||||
@ActionInput(name = "duration", label = "@text/action-input-duration-label", description = "@text/action-input-duration-desc") int durationMin) {
|
||||
@ActionInput(name = "duration-min", label = "@text/action-input-duration-min-label", description = "@text/action-input-duration-min-desc") long durationMin) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
if (automowerHandler == null) {
|
||||
logger.warn("Automower Action service ThingHandler is null!");
|
||||
@@ -115,7 +131,7 @@ public class AutomowerActions implements ThingActions {
|
||||
}
|
||||
}
|
||||
|
||||
public static void park(ThingActions actions, int durationMin) {
|
||||
public static void park(ThingActions actions, long durationMin) {
|
||||
((AutomowerActions) actions).park(durationMin);
|
||||
}
|
||||
|
||||
@@ -187,7 +203,7 @@ public class AutomowerActions implements ThingActions {
|
||||
|
||||
@RuleAction(label = "@text/action-set-work-area-label", description = "@text/action-set-work-area-desc")
|
||||
public void setWorkArea(
|
||||
@ActionInput(name = "workarea-id", label = "@text/action-input-workarea-id-label", description = "@text/action-input-workarea-id-desc") long workAreaId,
|
||||
@ActionInput(name = "work-area-id", label = "@text/action-input-work-area-id-label", description = "@text/action-input-work-area-id-desc") long workAreaId,
|
||||
@ActionInput(name = "enable", label = "@text/action-input-enable-label", description = "@text/action-input-enable-desc") boolean enable,
|
||||
@ActionInput(name = "cutting-height", label = "@text/action-input-cutting-height-label", description = "@text/action-input-cutting-height-desc") byte cuttingHeight) {
|
||||
AutomowerHandler automowerHandler = handler;
|
||||
@@ -220,7 +236,7 @@ public class AutomowerActions implements ThingActions {
|
||||
|
||||
@RuleAction(label = "@text/action-set-calendartask-label", description = "@text/action-set-calendartask-desc")
|
||||
public void setCalendarTask(
|
||||
@ActionInput(name = "workarea-id", label = "@text/action-input-workarea-id-label", description = "@text/action-input-workarea-id-desc") @Nullable Long workAreaId,
|
||||
@ActionInput(name = "work-area-id", label = "@text/action-input-work-area-id-label", description = "@text/action-input-work-area-id-desc") @Nullable Long workAreaId,
|
||||
@ActionInput(name = "start", label = "@text/action-input-start-label", description = "@text/action-input-start-desc") short[] start,
|
||||
@ActionInput(name = "duration", label = "@text/action-input-duration-label", description = "@text/action-input-duration-desc") short[] duration,
|
||||
@ActionInput(name = "monday", label = "@text/action-input-monday-label", description = "@text/action-input-monday-desc") boolean[] monday,
|
||||
|
||||
+18
-8
@@ -68,7 +68,7 @@ public class AutomowerBridge {
|
||||
this.automowerApi = new AutomowerConnectApi(httpClient);
|
||||
}
|
||||
|
||||
private AccessTokenResponse authenticate() throws AutomowerCommunicationException {
|
||||
public synchronized AccessTokenResponse authenticate() throws AutomowerCommunicationException {
|
||||
try {
|
||||
AccessTokenResponse result = authService.getAccessTokenResponse();
|
||||
if (result == null || result.isExpired(Instant.now(), 120)) {
|
||||
@@ -112,17 +112,27 @@ public class AutomowerBridge {
|
||||
* @param id The id of the mower
|
||||
* @param command The command that should be sent. Valid values are: "Start", "ResumeSchedule", "Pause", "Park",
|
||||
* "ParkUntilNextSchedule", "ParkUntilFurtherNotice"
|
||||
* @param commandDuration The duration of the command. This is only evaluated for "Start" and "Park" commands
|
||||
* @param commandDuration The duration of the command. This is only evaluated for "Start", "StartInWorkArea" and
|
||||
* "Park" commands
|
||||
* @param commandWorkAreaId The work area id to be used for the command. This is only evaluated for
|
||||
* "StartInWorkArea" command
|
||||
* @throws AutomowerCommunicationException In case the query cannot be executed successfully
|
||||
*/
|
||||
public void sendAutomowerCommand(String id, AutomowerCommand command, long commandDuration)
|
||||
throws AutomowerCommunicationException {
|
||||
MowerCommandAttributes attributes = new MowerCommandAttributes();
|
||||
attributes.setDuration(commandDuration);
|
||||
|
||||
public void sendAutomowerCommand(String id, AutomowerCommand command, @Nullable Long commandWorkAreaId,
|
||||
@Nullable Long commandDuration) throws AutomowerCommunicationException {
|
||||
MowerCommand mowerCommand = new MowerCommand();
|
||||
mowerCommand.setType(command.getCommand());
|
||||
mowerCommand.setAttributes(attributes);
|
||||
|
||||
if (commandDuration != null || commandWorkAreaId != null) {
|
||||
MowerCommandAttributes attributes = new MowerCommandAttributes();
|
||||
if (commandDuration != null) {
|
||||
attributes.setDuration(commandDuration);
|
||||
}
|
||||
if (commandWorkAreaId != null) {
|
||||
attributes.setWorkAreaId(commandWorkAreaId);
|
||||
}
|
||||
mowerCommand.setAttributes(attributes);
|
||||
}
|
||||
|
||||
MowerCommandRequest request = new MowerCommandRequest();
|
||||
request.setData(mowerCommand);
|
||||
|
||||
+118
-8
@@ -14,16 +14,26 @@ package org.openhab.binding.automower.internal.bridge;
|
||||
|
||||
import static org.openhab.binding.automower.internal.AutomowerBindingConstants.THING_TYPE_BRIDGE;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.Mower;
|
||||
import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerHandler;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
@@ -52,24 +62,86 @@ public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
private static final long DEFAULT_POLLING_INTERVAL_S = TimeUnit.HOURS.toSeconds(1);
|
||||
|
||||
private final OAuthFactory oAuthFactory;
|
||||
private @Nullable WebSocketSession webSocketSession;
|
||||
|
||||
private @Nullable OAuthClientService oAuthService;
|
||||
private @Nullable ScheduledFuture<?> automowerBridgePollingJob;
|
||||
private @Nullable AutomowerBridge bridge;
|
||||
private final HttpClient httpClient;
|
||||
private final WebSocketClient webSocketClient;
|
||||
private boolean closing;
|
||||
private Map<String, AutomowerHandler> automowerHandlers = new HashMap<>();
|
||||
|
||||
public AutomowerBridgeHandler(Bridge bridge, OAuthFactory oAuthFactory, HttpClient httpClient) {
|
||||
public AutomowerBridgeHandler(Bridge bridge, OAuthFactory oAuthFactory, HttpClient httpClient,
|
||||
WebSocketClient webSocketClient) {
|
||||
super(bridge);
|
||||
this.oAuthFactory = oAuthFactory;
|
||||
this.httpClient = httpClient;
|
||||
this.webSocketClient = webSocketClient;
|
||||
}
|
||||
|
||||
private void pollAutomowers(AutomowerBridge bridge) {
|
||||
public void registerAutomowerHandler(String mowerId, AutomowerHandler handler) {
|
||||
automowerHandlers.put(mowerId, handler);
|
||||
logger.trace("Registered AutomowerHandler for mower with ID: {}", mowerId);
|
||||
}
|
||||
|
||||
public void unregisterAutomowerHandler(String mowerId) {
|
||||
automowerHandlers.remove(mowerId);
|
||||
logger.trace("Unregistered AutomowerHandler for mower with ID: {}", mowerId);
|
||||
}
|
||||
|
||||
public WebSocketClient getWebSocketClient() {
|
||||
return webSocketClient;
|
||||
}
|
||||
|
||||
public ScheduledExecutorService getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
public @Nullable WebSocketSession getWebSocketSession() {
|
||||
return webSocketSession;
|
||||
}
|
||||
|
||||
public void setWebSocketSession(@Nullable WebSocketSession webSocketSession) {
|
||||
this.webSocketSession = webSocketSession;
|
||||
}
|
||||
|
||||
public boolean isClosing() {
|
||||
return closing;
|
||||
}
|
||||
|
||||
public void setClosing(boolean closing) {
|
||||
this.closing = closing;
|
||||
}
|
||||
|
||||
public @Nullable AutomowerHandler getAutomowerHandlerByThingId(@Nullable String thingId) {
|
||||
return automowerHandlers.get(thingId);
|
||||
}
|
||||
|
||||
public synchronized void pollAutomowers(AutomowerBridge bridge) {
|
||||
MowerListResult automowers;
|
||||
try {
|
||||
automowers = bridge.getAutomowers();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
logger.debug("Found {} automowers", automowers.getData().size());
|
||||
List<Mower> mowers = automowers.getData();
|
||||
if (mowers == null || mowers.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-no-mowers-found");
|
||||
logger.debug("No automowers found in the response from REST API");
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
logger.debug("Found {} automowers in the response from REST API", mowers.size());
|
||||
// Update all known AutomowerHandlers with the data from the REST API
|
||||
for (Mower mower : mowers) {
|
||||
String id = mower.getId();
|
||||
AutomowerHandler automowerHandler = getAutomowerHandlerByThingId(id);
|
||||
if (automowerHandler != null) {
|
||||
logger.debug("Data from REST API for known AutomowerHandler with id: {}", id);
|
||||
automowerHandler.updateAutomowerStateViaREST(mower);
|
||||
} else {
|
||||
logger.debug("Data from REST API for unknown AutomowerHandler with id: {}", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/comm-error-query-mowers-failed");
|
||||
@@ -79,16 +151,29 @@ public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
closing = true;
|
||||
|
||||
AutomowerBridge currentBridge = bridge;
|
||||
if (currentBridge != null) {
|
||||
stopAutomowerBridgePolling(currentBridge);
|
||||
bridge = null;
|
||||
}
|
||||
|
||||
WebSocketSession webSocketSession = this.webSocketSession;
|
||||
if (webSocketSession != null) {
|
||||
try {
|
||||
webSocketSession.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to close WebSocket session: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
OAuthClientService oAuthService = this.oAuthService;
|
||||
if (oAuthService != null) {
|
||||
oAuthFactory.ungetOAuthService(thing.getUID().getAsString());
|
||||
this.oAuthService = null;
|
||||
}
|
||||
logger.debug("Bridge {} disposed", thing.getUID().getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,9 +196,12 @@ public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
HUSQVARNA_API_TOKEN_URL, null, appKey, appSecret, null, null);
|
||||
this.oAuthService = oAuthService;
|
||||
|
||||
if (bridge == null) {
|
||||
if (this.bridge == null) {
|
||||
AutomowerBridge currentBridge = new AutomowerBridge(oAuthService, appKey, httpClient, scheduler);
|
||||
bridge = currentBridge;
|
||||
this.bridge = currentBridge;
|
||||
// connect WebSocket and poll automower state via REST API once after connection
|
||||
connectWebSocket(new AutomowerWebSocketAdapter(this, currentBridge));
|
||||
// setup polling of automowers via REST API
|
||||
startAutomowerBridgePolling(currentBridge, pollingIntervalS);
|
||||
}
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
@@ -130,8 +218,8 @@ public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
ScheduledFuture<?> currentPollingJob = automowerBridgePollingJob;
|
||||
if (currentPollingJob == null) {
|
||||
final long pollingIntervalToUse = pollingIntervalS == null ? DEFAULT_POLLING_INTERVAL_S : pollingIntervalS;
|
||||
automowerBridgePollingJob = scheduler.scheduleWithFixedDelay(() -> pollAutomowers(bridge), 1,
|
||||
pollingIntervalToUse, TimeUnit.SECONDS);
|
||||
automowerBridgePollingJob = scheduler.scheduleWithFixedDelay(() -> pollAutomowers(bridge),
|
||||
pollingIntervalToUse, pollingIntervalToUse, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,4 +252,26 @@ public class AutomowerBridgeHandler extends BaseBridgeHandler {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void connectWebSocket(AutomowerWebSocketAdapter webSocketAdapter) {
|
||||
try {
|
||||
AutomowerBridge bridge = this.bridge;
|
||||
if (bridge != null) {
|
||||
String accessToken = bridge.authenticate().getAccessToken();
|
||||
if (accessToken == null) {
|
||||
logger.error("No OAuth2 access token available for WebSocket connection");
|
||||
return;
|
||||
}
|
||||
String wsUrl = "wss://ws.openapi.husqvarna.dev/v1";
|
||||
ClientUpgradeRequest request = new ClientUpgradeRequest();
|
||||
request.setHeader("Authorization", "Bearer " + accessToken);
|
||||
webSocketSession = (WebSocketSession) webSocketClient
|
||||
.connect(webSocketAdapter, URI.create(wsUrl), request).get();
|
||||
} else {
|
||||
logger.error("Bridge is null, cannot connect WebSocket");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to start WebSocket client: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package org.openhab.binding.automower.internal.bridge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.frames.PongFrame;
|
||||
import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
|
||||
import org.openhab.binding.automower.internal.things.AutomowerHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link AutomowerWebSocketAdapter} handles the WebSocket Connection of the Husqvarna web service.
|
||||
*
|
||||
* @author MikeTheTux - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@WebSocket
|
||||
public class AutomowerWebSocketAdapter {
|
||||
private final AutomowerBridgeHandler handler;
|
||||
private final AutomowerBridge bridge;
|
||||
private final Logger logger = LoggerFactory.getLogger(AutomowerWebSocketAdapter.class);
|
||||
private @Nullable ScheduledFuture<?> connectionTracker;
|
||||
private int unansweredPings = 0;
|
||||
private static final int MAX_UNANSWERED_PINGS = 5;
|
||||
|
||||
private ByteBuffer pingPayload = ByteBuffer.wrap("ping".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
public AutomowerWebSocketAdapter(AutomowerBridgeHandler handler, AutomowerBridge bridge) {
|
||||
this.handler = handler;
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
@OnWebSocketConnect
|
||||
public synchronized void onConnect(Session session) {
|
||||
handler.setClosing(false);
|
||||
unansweredPings = 0;
|
||||
|
||||
logger.debug("Connected to Husqvarna WebSocket ({})", session.getRemoteAddress().getHostString());
|
||||
|
||||
// Initialize MowerStatus via polling the REST API
|
||||
logger.debug("Polling Automowers for initial state / after reconnect of WebSocket");
|
||||
// Poll all automowers to get their initial state
|
||||
// This is necessary because the WebSocket does not provide the initial state
|
||||
// and we need to have the initial state before subscribing to the WebSocket messages
|
||||
// This will also recover potential lost WebSocket messages during WebSocket reconnect
|
||||
handler.pollAutomowers(bridge);
|
||||
|
||||
// Subscribe to all messages after connecting
|
||||
try {
|
||||
String subscribeAllMessage = "{\"type\":\"subscribe\",\"topics\":[\"*\"]}";
|
||||
session.getRemote().sendString(subscribeAllMessage);
|
||||
logger.debug("Sent subscription message to subscribe to all topics");
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to send subscription message: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// Cancel previous ping task if it exists
|
||||
ScheduledFuture<?> connectionTracker = this.connectionTracker;
|
||||
if (connectionTracker != null && !connectionTracker.isCancelled()) {
|
||||
logger.trace("Cancelling previous connectionTracker (ping)");
|
||||
connectionTracker.cancel(true);
|
||||
}
|
||||
logger.trace("Starting connectionTracker (ping)");
|
||||
// start sending PING every minute
|
||||
this.connectionTracker = handler.getScheduler().scheduleWithFixedDelay(this::sendKeepAlivePing, 1, 1,
|
||||
TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
@OnWebSocketFrame
|
||||
public synchronized void onFrame(Frame pong) {
|
||||
if (pong instanceof PongFrame) {
|
||||
unansweredPings = 0;
|
||||
// logger.trace("Pong received");
|
||||
}
|
||||
}
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onMessage(String message) {
|
||||
try {
|
||||
if (!message.isBlank()) {
|
||||
JsonObject event = JsonParser.parseString(message).getAsJsonObject();
|
||||
if (event.has("id")) {
|
||||
String id = event.get("id").getAsString();
|
||||
AutomowerHandler automowerHandler = handler.getAutomowerHandlerByThingId(id);
|
||||
if (automowerHandler != null) {
|
||||
logger.debug("Message from WebSocket for known AutomowerHandler: {}", message);
|
||||
automowerHandler.processWebSocketMessage(event);
|
||||
} else {
|
||||
logger.debug("Message from WebSocket for unknown AutomowerHandler: {}", message);
|
||||
}
|
||||
} else {
|
||||
logger.trace("Message from WebSocket without Id: {}", message);
|
||||
}
|
||||
} else {
|
||||
logger.trace("Received empty message from WebSocket");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to process WebSocket message: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@OnWebSocketClose
|
||||
public void onClose(int statusCode, String reason) {
|
||||
logger.debug("WebSocket closed: {} - {}", statusCode, reason);
|
||||
|
||||
// Cancel ping task on disconnect
|
||||
final ScheduledFuture<?> connectionTracker = this.connectionTracker;
|
||||
if (connectionTracker != null) {
|
||||
logger.trace("Cancelling connectionTracker (ping)");
|
||||
connectionTracker.cancel(true);
|
||||
}
|
||||
|
||||
if (!handler.isClosing()) {
|
||||
try {
|
||||
logger.debug("Reconnecting to Husqvarna Webservice ()");
|
||||
handler.connectWebSocket(this);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to restart WebSocket client: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnWebSocketError
|
||||
public void onError(Throwable cause) {
|
||||
logger.error("WebSocket error: {}", cause.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a ping to tell the Husqvarna smart system that the client is alive.
|
||||
*/
|
||||
private synchronized void sendKeepAlivePing() {
|
||||
try {
|
||||
WebSocketSession webSocketSession = handler.getWebSocketSession();
|
||||
if (webSocketSession != null) {
|
||||
String accessToken = bridge.authenticate().getAccessToken();
|
||||
if (unansweredPings > MAX_UNANSWERED_PINGS || accessToken == null) {
|
||||
webSocketSession.close(1000, "Timeout: manually closing dead connection");
|
||||
} else {
|
||||
if (webSocketSession.isOpen()) {
|
||||
try {
|
||||
// logger.trace("Sending ping ...");
|
||||
webSocketSession.getRemote().sendPing(pingPayload);
|
||||
++unansweredPings;
|
||||
} catch (IOException ex) {
|
||||
logger.warn("Error while sending ping: {}", ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("WebSocket session is null, cannot send ping");
|
||||
}
|
||||
} catch (AutomowerCommunicationException e) {
|
||||
logger.error("Failed to authenticate while sending keep-alive ping: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class AutomowerConnectApi extends HusqvarnaApi {
|
||||
request.method(HttpMethod.GET);
|
||||
|
||||
ContentResponse response = executeRequest(appKey, token, request);
|
||||
|
||||
logger.trace("getMowers: {}", response.getContentAsString());
|
||||
return parseResponse(response, MowerListResult.class);
|
||||
}
|
||||
|
||||
|
||||
+12
-3
@@ -16,13 +16,22 @@ package org.openhab.binding.automower.internal.rest.api.automowerconnect.dto;
|
||||
* @author Markus Pfleger - Initial contribution
|
||||
*/
|
||||
public class MowerCommandAttributes {
|
||||
private long duration;
|
||||
private Long duration;
|
||||
private Long workAreaId;
|
||||
|
||||
public long getDuration() {
|
||||
public Long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(long duration) {
|
||||
public void setDuration(Long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public Long getWorkAreaId() {
|
||||
return workAreaId;
|
||||
}
|
||||
|
||||
public void setWorkAreaId(Long workAreaId) {
|
||||
this.workAreaId = workAreaId;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class StayOutZone {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabed(Boolean enabled) {
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -27,6 +27,7 @@ import org.openhab.core.thing.ChannelUID;
|
||||
@NonNullByDefault
|
||||
public enum AutomowerCommand {
|
||||
START("Start", AutomowerBindingConstants.CHANNEL_COMMAND_START),
|
||||
START_IN_WORK_AREA("StartInWorkArea", AutomowerBindingConstants.CHANNEL_COMMAND_START_IN_WORK_AREA),
|
||||
RESUME_SCHEDULE("ResumeSchedule", AutomowerBindingConstants.CHANNEL_COMMAND_RESUME_SCHEDULE),
|
||||
PAUSE("Pause", AutomowerBindingConstants.CHANNEL_COMMAND_PAUSE),
|
||||
PARK("Park", AutomowerBindingConstants.CHANNEL_COMMAND_PARK),
|
||||
|
||||
-9
@@ -23,7 +23,6 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
@NonNullByDefault
|
||||
public class AutomowerConfiguration {
|
||||
public @Nullable String mowerId;
|
||||
public @Nullable Integer pollingInterval;
|
||||
public @Nullable String mowerZoneId;
|
||||
|
||||
@Nullable
|
||||
@@ -35,14 +34,6 @@ public class AutomowerConfiguration {
|
||||
this.mowerId = mowerId;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPollingInterval() {
|
||||
return pollingInterval;
|
||||
}
|
||||
|
||||
public void setPollingInterval(Integer pollingInterval) {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMowerZoneId() {
|
||||
return mowerZoneId;
|
||||
|
||||
+927
-589
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
|
||||
<type>binding</type>
|
||||
<name>Automower Binding</name>
|
||||
<description>Binding to interact with Husquvarna Automower robots.</description>
|
||||
<description>Binding for Husqvarna Automower® robotic lawn mowers</description>
|
||||
<connection>cloud</connection>
|
||||
|
||||
</addon:addon>
|
||||
|
||||
+131
-117
@@ -1,36 +1,33 @@
|
||||
# add-on
|
||||
|
||||
addon.automower.name = Automower Binding
|
||||
addon.automower.description = Binding to interact with Husquvarna Automower robots.
|
||||
addon.automower.description = Binding for Husqvarna Automower® robotic lawn mowers
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.automower.automower.label = Automower
|
||||
thing-type.automower.automower.label = Automower®
|
||||
thing-type.automower.automower.description = An automatic lawn mower
|
||||
thing-type.automower.bridge.label = Automower Connect Bridge
|
||||
thing-type.automower.bridge.description = The bridge to communicate with the Automower Connect API
|
||||
thing-type.automower.bridge.label = Automower® Connect Bridge
|
||||
thing-type.automower.bridge.description = The bridge to communicate with the Automower® Connect API
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.automower.automower.mowerId.label = Automower Id
|
||||
thing-type.config.automower.automower.mowerId.description = The Id of an automower as used by the Automower Connect Api to identify a mower
|
||||
thing-type.config.automower.automower.mowerId.label = Automower® Id
|
||||
thing-type.config.automower.automower.mowerId.description = The Id of an Automower® as used by the Automower® Connect API to identify a Automower®. This is automatically filled when the thing is discovered.
|
||||
thing-type.config.automower.automower.mowerZoneId.label = TimeZone
|
||||
thing-type.config.automower.automower.mowerZoneId.description = Time zone of the mower (e.g. Europe/Berlin)
|
||||
thing-type.config.automower.automower.pollingInterval.label = Polling Interval
|
||||
thing-type.config.automower.automower.pollingInterval.description = How often the current automower state should be polled in seconds
|
||||
thing-type.config.automower.automower.mowerZoneId.description = Time zone of the Automower® (e.g. Europe/Berlin). Default is the time zone configured in openHAB
|
||||
thing-type.config.automower.bridge.appKey.label = Application Key
|
||||
thing-type.config.automower.bridge.appKey.description = The Application Key is required to communicate with the Automower Connect API at https://developer.husqvarnagroup.cloud/. It can be obtained by registering an Application on the Husqvarna Website. This application also needs to be connected to the "Authentication API" and the "Automower Connect API"
|
||||
thing-type.config.automower.bridge.appKey.description = The Application Key is required to communicate with the Automower® Connect API. It can be obtained by registering an Application on https://developer.husqvarnagroup.cloud/. This application needs to be connected to the "Authentication API" and the "Automower® Connect API". https://developer.husqvarnagroup.cloud/docs/getting-started
|
||||
thing-type.config.automower.bridge.appSecret.label = Application Secret
|
||||
thing-type.config.automower.bridge.appSecret.description = The Application Secret is required to communicate with the Automower Connect API at https://developer.husqvarnagroup.cloud/. It can be obtained by registering an Application on the Husqvarna Website.
|
||||
thing-type.config.automower.bridge.appSecret.description = The Application Secret is required to communicate with the Automower® Connect API. See "Application Key" for further details
|
||||
thing-type.config.automower.bridge.pollingInterval.label = Polling Interval
|
||||
thing-type.config.automower.bridge.pollingInterval.description = How often the available automowers should be queried in seconds
|
||||
thing-type.config.automower.bridge.pollingInterval.description = How often the current Automower® states should be polled using REST API
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.automower.calendarTasksType.label = Calendar Tasks
|
||||
channel-group-type.automower.commandsType.label = Commands
|
||||
channel-group-type.automower.messagesType.label = Messages
|
||||
channel-group-type.automower.positionsType.label = Positions
|
||||
channel-group-type.automower.settingsType.label = Settings
|
||||
channel-group-type.automower.statisticsType.label = Statistics
|
||||
channel-group-type.automower.statusType.label = Status
|
||||
@@ -50,7 +47,7 @@ channel-type.automower.activityType.state.option.LEAVING = Leaving charging stat
|
||||
channel-type.automower.activityType.state.option.PARKED_IN_CS = Parked in charging station
|
||||
channel-type.automower.activityType.state.option.STOPPED_IN_GARDEN = Stopped in garden
|
||||
channel-type.automower.batteryType.label = Battery
|
||||
channel-type.automower.batteryType.description = The battery level of the mower at the time of last update
|
||||
channel-type.automower.batteryType.description = The battery state of charge in percent
|
||||
channel-type.automower.calendarTaskDurationType.label = Duration
|
||||
channel-type.automower.calendarTaskDurationType.description = Duration time
|
||||
channel-type.automower.calendarTaskDurationType.state.pattern = %1$tHh:%1$tMm
|
||||
@@ -74,36 +71,34 @@ channel-type.automower.calendarTaskWednesdayType.description = Enabled on Wednes
|
||||
channel-type.automower.calendarTaskWorkAreaIdType.label = Work Area Id of Calendar
|
||||
channel-type.automower.calendarTaskWorkAreaIdType.description = Work Area Id mapped to this calendar
|
||||
channel-type.automower.errorCodeType.label = Error Code
|
||||
channel-type.automower.errorCodeType.description = The error code at the time of last update
|
||||
channel-type.automower.errorCodeType.description = The current error code
|
||||
channel-type.automower.errorConfirmableType.label = Error Confirmable
|
||||
channel-type.automower.errorConfirmableType.description = If the mower has an Error Code this attribute states if the error is confirmable
|
||||
channel-type.automower.errorConfirmableType.description = If the Automower® has an error, this attribute states if the error is confirmable
|
||||
channel-type.automower.errorMessageType.label = Error Message
|
||||
channel-type.automower.errorMessageType.description = The error message at the time of last update
|
||||
channel-type.automower.errorMessageType.description = The current error message
|
||||
channel-type.automower.errorTimestampType.label = Error Time
|
||||
channel-type.automower.errorTimestampType.description = The time when the error occurred
|
||||
channel-type.automower.errorTimestampType.description = The time when the current error occurred
|
||||
channel-type.automower.externalReasonType.label = External Reason
|
||||
channel-type.automower.externalReasonType.description = The channel providing an external reason that restrics current planner operation.
|
||||
channel-type.automower.externalReasonType.description = An external reason set by i.e. Google Assistant or Amazon Alexa that restrics the current planner operation
|
||||
channel-type.automower.inactiveReasonType.label = Inactive Reason
|
||||
channel-type.automower.inactiveReasonType.description = The current reason for being inactive
|
||||
channel-type.automower.inactiveReasonType.state.option.NONE = No inactive reason
|
||||
channel-type.automower.inactiveReasonType.state.option.PLANNING = The mower is planning a path or a work area
|
||||
channel-type.automower.inactiveReasonType.state.option.PLANNING = The Automower® is planning a path or a Work Area
|
||||
channel-type.automower.inactiveReasonType.state.option.SEARCHING_FOR_SATELLITES = Waiting for fix when using EPOS
|
||||
channel-type.automower.lastPollUpdateType.label = Last Poll Update
|
||||
channel-type.automower.lastPollUpdateType.description = The time when the binding polled the last update from the cloud
|
||||
channel-type.automower.lastPositionType.label = Last GPS Position
|
||||
channel-type.automower.lastPositionType.description = Last GPS position of the mower
|
||||
channel-type.automower.lastUpdateType.label = Last Update
|
||||
channel-type.automower.lastUpdateType.description = The time when the mower sent the last update
|
||||
channel-type.automower.messageCodeType.label = Code
|
||||
channel-type.automower.messageCodeType.description = (Error) code of the event
|
||||
channel-type.automower.messagePositionType.label = GPS Position
|
||||
channel-type.automower.messagePositionType.description = GPS Position of the event (if available)
|
||||
channel-type.automower.messageSeverityType.label = Severity
|
||||
channel-type.automower.messageSeverityType.description = The severity of the event
|
||||
channel-type.automower.messageTimeType.label = Timestamp
|
||||
channel-type.automower.messageTimeType.description = Timestamp when the event occurred
|
||||
channel-type.automower.messageType.label = Message
|
||||
channel-type.automower.messageType.description = The Message
|
||||
channel-type.automower.lastUpdateType.description = The time when the Automower® sent the last update
|
||||
channel-type.automower.messageCodeType.label = Last Error Code
|
||||
channel-type.automower.messageCodeType.description = The last error code
|
||||
channel-type.automower.messagePositionType.label = Message GPS Position
|
||||
channel-type.automower.messagePositionType.description = GPS position of the last event (if available)
|
||||
channel-type.automower.messageSeverityType.label = Message Severity
|
||||
channel-type.automower.messageSeverityType.description = The severity of the last error
|
||||
channel-type.automower.messageTimeType.label = Last Error Time
|
||||
channel-type.automower.messageTimeType.description = The time when the last error occurred
|
||||
channel-type.automower.messageType.label = Last Error Message
|
||||
channel-type.automower.messageType.description = The last error message
|
||||
channel-type.automower.modeType.label = Mode
|
||||
channel-type.automower.modeType.description = The current mode
|
||||
channel-type.automower.modeType.state.option.MAIN_AREA = Main Area
|
||||
@@ -111,26 +106,26 @@ channel-type.automower.modeType.state.option.SECONDARY_AREA = Secondary Area
|
||||
channel-type.automower.modeType.state.option.HOME = Home
|
||||
channel-type.automower.modeType.state.option.DEMO = Demo
|
||||
channel-type.automower.modeType.state.option.UNKNOWN = Unknown
|
||||
channel-type.automower.nameType.label = Automower Name
|
||||
channel-type.automower.nameType.description = The channel providing the automower name
|
||||
channel-type.automower.nextStartType.label = Next Auto Start
|
||||
channel-type.automower.nextStartType.description = The channel providing the time for the next auto start. If the mower is charging then the value is the estimated time when it will be leaving the charging station. If the mower is about to start now, the value is NULL.
|
||||
channel-type.automower.nameType.label = Automower® Name
|
||||
channel-type.automower.nameType.description = The name of the Automower®
|
||||
channel-type.automower.nextStartType.label = Next Start
|
||||
channel-type.automower.nextStartType.description = The time for the next scheduled start. If the Automower® is charging then the value is the estimated time when it will be leaving the charging station. If the Automower® is about to start now, the value is NULL
|
||||
channel-type.automower.overrideActionType.label = Override Action
|
||||
channel-type.automower.overrideActionType.description = The channel providing an action that overrides current planner operation.
|
||||
channel-type.automower.overrideActionType.description = The action that overrides the current planner operation
|
||||
channel-type.automower.park.label = Park with Duration
|
||||
channel-type.automower.park.description = Park for a duration in minutes
|
||||
channel-type.automower.park.description = Park the Automower® for the given duration, overriding the schedule
|
||||
channel-type.automower.parkUntilFurtherNotice.label = Park and Pause the Schedule
|
||||
channel-type.automower.parkUntilFurtherNotice.description = Park and pause the mower schedule until manual resume
|
||||
channel-type.automower.parkUntilFurtherNotice.description = Park the Automower® until it is started again by the start action/command or the schedule gets resumed
|
||||
channel-type.automower.parkUntilNextSchedule.label = Park Until Next Schedule
|
||||
channel-type.automower.parkUntilNextSchedule.description = Park until next schedule
|
||||
channel-type.automower.parkUntilNextSchedule.description = Park the Automower®, fully charge it and start afterwards according to the schedule
|
||||
channel-type.automower.pause.label = Pause
|
||||
channel-type.automower.pause.description = Pause the mower now until manual resume
|
||||
channel-type.automower.pause.description = Pause the Automower® at the current location until manual resume
|
||||
channel-type.automower.pollUpdateType.label = Poll Update
|
||||
channel-type.automower.pollUpdateType.description = Poll mower status update from the cloud
|
||||
channel-type.automower.positionType.label = GPS Position
|
||||
channel-type.automower.positionType.description = A waypoint of the mower's activity
|
||||
channel-type.automower.pollUpdateType.description = Poll Automower® status update from the cloud
|
||||
channel-type.automower.positionType.label = Last GPS Position
|
||||
channel-type.automower.positionType.description = Last GPS position of the Automower®
|
||||
channel-type.automower.restrictedReasonType.label = Restricted Reason
|
||||
channel-type.automower.restrictedReasonType.description = The channel providing a reason that restrics current planner operation.
|
||||
channel-type.automower.restrictedReasonType.description = The reason that restrics the current planner operation
|
||||
channel-type.automower.restrictedReasonType.state.option.NONE = No restricted reason
|
||||
channel-type.automower.restrictedReasonType.state.option.WEEK_SCHEDULE = Restricted by week schedule
|
||||
channel-type.automower.restrictedReasonType.state.option.PARK_OVERRIDE = Forced to park
|
||||
@@ -138,25 +133,26 @@ channel-type.automower.restrictedReasonType.state.option.SENSOR = Restricted by
|
||||
channel-type.automower.restrictedReasonType.state.option.DAILY_LIMIT = Restricted by daily limit
|
||||
channel-type.automower.restrictedReasonType.state.option.FOTA = Restricted by FOTA transfer
|
||||
channel-type.automower.restrictedReasonType.state.option.FROST = Restricted by frost sensor
|
||||
channel-type.automower.restrictedReasonType.state.option.ALL_WORK_AREAS_COMPLETED = Restricted: All work areas completed
|
||||
channel-type.automower.restrictedReasonType.state.option.ALL_WORK_AREAS_COMPLETED = Restricted: All Work Areas completed
|
||||
channel-type.automower.restrictedReasonType.state.option.EXTERNAL = Restricted by external reason
|
||||
channel-type.automower.resumeSchedule.label = Resume Schedule
|
||||
channel-type.automower.resumeSchedule.description = Resume schedule
|
||||
channel-type.automower.resumeSchedule.description = Resume the schedule of the Automower®
|
||||
channel-type.automower.settingCuttingHeightType.label = Cutting Height
|
||||
channel-type.automower.settingCuttingHeightType.description = Prescaled cutting height, range: 1-9
|
||||
channel-type.automower.settingHeadlightModeType.label = Headlight Mode
|
||||
channel-type.automower.settingHeadlightModeType.description = Information about headlights
|
||||
channel-type.automower.start.label = Start with Duration
|
||||
channel-type.automower.start.description = Start for a duration in minutes
|
||||
channel-type.automower.start.description = Start the Automower® for the given duration, overriding the schedule
|
||||
channel-type.automower.startInWorkArea.label = Start in Work Area
|
||||
channel-type.automower.startInWorkArea.description = Start the Automower® in the given Work Area, overriding the schedule. The Automower® will continue forever
|
||||
channel-type.automower.statCuttingBladeUsageTimeType.label = Cutting Blade Usage Time
|
||||
channel-type.automower.statCuttingBladeUsageTimeType.description = The time since the last reset of the cutting blade usage counter
|
||||
channel-type.automower.statDownTimeType.label = Down Time
|
||||
channel-type.automower.statDownTimeType.description = The time the mower has been disconnected from the cloud
|
||||
channel-type.automower.statDownTimeType.state.pattern = %1$tHh:%1$tMm:%1$tSs
|
||||
channel-type.automower.statDownTimeType.description = The time the Automower® has been disconnected from the cloud
|
||||
channel-type.automower.statDownTimeType.state.pattern = %1$tdd:%1$tHh:%1$tMm:%1$tSs
|
||||
channel-type.automower.statNumberOfChargingCyclesType.label = Number of Charging Cycles
|
||||
channel-type.automower.statNumberOfChargingCyclesType.description = Number of charging cycles
|
||||
channel-type.automower.statNumberOfCollisionsType.label = Number of Collisions
|
||||
channel-type.automower.statNumberOfCollisionsType.description = The total number of collisions
|
||||
channel-type.automower.statNumberOfCollisionsType.description = Total number of collisions
|
||||
channel-type.automower.statTotalChargingTimeType.label = Total Charging Time
|
||||
channel-type.automower.statTotalChargingTimeType.description = Total charging time
|
||||
channel-type.automower.statTotalCuttingPercentType.label = Relative Total Cutting Time
|
||||
@@ -172,8 +168,8 @@ channel-type.automower.statTotalSearchingPercentType.description = The total sea
|
||||
channel-type.automower.statTotalSearchingTimeType.label = Total Searching Time
|
||||
channel-type.automower.statTotalSearchingTimeType.description = The total searching time
|
||||
channel-type.automower.statUpTimeType.label = Up Time
|
||||
channel-type.automower.statUpTimeType.description = The time the mower has been connected to the cloud
|
||||
channel-type.automower.statUpTimeType.state.pattern = %1$tHh:%1$tMm:%1$tSs
|
||||
channel-type.automower.statUpTimeType.description = The time the Automower® has been connected to the cloud
|
||||
channel-type.automower.statUpTimeType.state.pattern = %1$tdd:%1$tHh:%1$tMm:%1$tSs
|
||||
channel-type.automower.stateType.label = State
|
||||
channel-type.automower.stateType.description = The current state
|
||||
channel-type.automower.stateType.state.option.UNKNOWN = Unknown
|
||||
@@ -181,7 +177,7 @@ channel-type.automower.stateType.state.option.NOT_APPLICABLE = N/A
|
||||
channel-type.automower.stateType.state.option.PAUSED = Paused by user
|
||||
channel-type.automower.stateType.state.option.IN_OPERATION = Working
|
||||
channel-type.automower.stateType.state.option.WAIT_UPDATING = Downloading new firmware
|
||||
channel-type.automower.stateType.state.option.WAIT_POWER_UP = Booting mower
|
||||
channel-type.automower.stateType.state.option.WAIT_POWER_UP = Booting Automower®
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_NONE = No restricted reason
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_WEEK_SCHEDULE = Restricted by week schedule
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_PARK_OVERRIDE = Forced to park
|
||||
@@ -189,7 +185,7 @@ channel-type.automower.stateType.state.option.RESTRICTED_SENSOR = Restricted by
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_DAILY_LIMIT = Restricted by daily limit
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_FOTA = Restricted by FOTA transfer
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_FROST = Restricted by frost sensor
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_ALL_WORK_AREAS_COMPLETED = Restricted: All work areas completed
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_ALL_WORK_AREAS_COMPLETED = Restricted: All Work Areas completed
|
||||
channel-type.automower.stateType.state.option.RESTRICTED_EXTERNAL = Restricted by external reason
|
||||
channel-type.automower.stateType.state.option.OFF = Off
|
||||
channel-type.automower.stateType.state.option.STOPPED = Stopped: Manual intervention required
|
||||
@@ -197,29 +193,47 @@ channel-type.automower.stateType.state.option.ERROR = Error
|
||||
channel-type.automower.stateType.state.option.FATAL_ERROR = Fatal error
|
||||
channel-type.automower.stateType.state.option.ERROR_AT_POWER_UP = Boot error
|
||||
channel-type.automower.workAreaIdType.label = Work Area Id
|
||||
channel-type.automower.workAreaIdType.description = Id of the active work area
|
||||
channel-type.automower.workAreaIdType.description = Id of the active Work Area
|
||||
channel-type.automower.workAreaType.label = Work Area Name
|
||||
channel-type.automower.workAreaType.description = Name of the active work area
|
||||
channel-type.automower.workAreaType.description = Name of the active Work Area
|
||||
channel-type.automower.workareaCuttingHeightType.label = Cutting Height
|
||||
channel-type.automower.workareaCuttingHeightType.description = Cutting height of the work area, range: 0-100
|
||||
channel-type.automower.workareaCuttingHeightType.description = Cutting height of the Work Area, range: 0-100
|
||||
channel-type.automower.workareaEnabledType.label = Work Area Enabled
|
||||
channel-type.automower.workareaEnabledType.description = If the work area is enabled or disabled
|
||||
channel-type.automower.workareaEnabledType.description = If the Work Area is enabled or disabled
|
||||
channel-type.automower.workareaIdType.label = Work Area Id
|
||||
channel-type.automower.workareaIdType.description = Id of the Work Area
|
||||
channel-type.automower.workareaLastTimeCompletedType.label = Last Time Completed
|
||||
channel-type.automower.workareaLastTimeCompletedType.description = Timestamp when the work area was last completed. EPOS mowers and systematic mowing work areas only.
|
||||
channel-type.automower.workareaLastTimeCompletedType.description = Timestamp when the Work Area was last completed. EPOS Automower® and systematic mowing Work Areas only
|
||||
channel-type.automower.workareaNameType.label = Work Area Name
|
||||
channel-type.automower.workareaNameType.description = Name of the work area
|
||||
channel-type.automower.workareaNameType.description = Name of the Work Area
|
||||
channel-type.automower.workareaProgressType.label = Work Area Progress
|
||||
channel-type.automower.workareaProgressType.description = The progress on a work area. EPOS mowers and systematic mowing work areas only.
|
||||
channel-type.automower.workareaProgressType.description = The progress on a Work Area. EPOS Automower® and systematic mowing Work Areas only
|
||||
channel-type.automower.zoneDirtyType.label = Stayout Zones Dirty Flag
|
||||
channel-type.automower.zoneDirtyType.description = If the stay-out zones are synchronized with the Husqvarna cloud. If the map is dirty you can not enable or disable a stay-out zone.
|
||||
channel-type.automower.zoneDirtyType.description = If the stay-out zones are synchronized with the Husqvarna cloud. If the map is dirty you can not enable or disable a stay-out zone
|
||||
channel-type.automower.zoneEnabledType.label = Stayout Zone Enabled
|
||||
channel-type.automower.zoneEnabledType.description = If the Stayout zone is enabled, the Automower® will not access the zone
|
||||
channel-type.automower.zoneEnabledType.description = If the stay-out zone is enabled, the Automower® will not access the zone
|
||||
channel-type.automower.zoneIdType.label = Stayout Zone Id
|
||||
channel-type.automower.zoneIdType.description = Id of the Stayout zone
|
||||
channel-type.automower.zoneIdType.description = Id of the stay-out zone
|
||||
channel-type.automower.zoneNameType.label = Stayout Zone Name
|
||||
channel-type.automower.zoneNameType.description = The name of the Stayout zone
|
||||
channel-type.automower.zoneNameType.description = The name of the stay-out zone
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.automower.settingHeadlightModeType.description = Headlight Mode
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.automower.automower.pollingInterval.label = Polling Interval
|
||||
thing-type.config.automower.automower.pollingInterval.description = How often the current Automower® state should be polled
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.automower.positionsType.label = Positions
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.automower.lastPositionType.label = Last GPS Position
|
||||
channel-type.automower.lastPositionType.description = Last GPS position of the mower
|
||||
|
||||
# channel types
|
||||
|
||||
@@ -238,7 +252,7 @@ channel-type.automower.plannerRestrictedReasonType.state.option.SENSOR = Restric
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.DAILY_LIMIT = Restricted by daily limit
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.FOTA = Restricted by FOTA transfer
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.FROST = Restricted by frost sensor
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.ALL_WORK_AREAS_COMPLETED = Restricted: All work areas completed
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.ALL_WORK_AREAS_COMPLETED = Restricted: All Work Areas completed
|
||||
channel-type.automower.plannerRestrictedReasonType.state.option.EXTERNAL = Restricted by external reason
|
||||
|
||||
# channel types
|
||||
@@ -277,78 +291,78 @@ channel-type.automower.calendarTasksType.description = The channel providing a J
|
||||
|
||||
# actions
|
||||
|
||||
action-input-duration-label = duration
|
||||
action-input-duration-desc = The duration of the automower command in minutes
|
||||
action-park-label = park the automower
|
||||
action-park-desc = Parks the automower for a defined amount of time, overriding its schedule.
|
||||
action-input-duration-min-label = duration (min)
|
||||
action-input-duration-min-desc = The duration of the Automower® command in minutes
|
||||
action-input-duration-min-opt-label = duration (min)
|
||||
action-input-duration-min-opt-desc = The duration of the Automower® command in minutes. If duration is skipped the Automower® will continue forever
|
||||
action-input-work-area-id-label = work area id
|
||||
action-input-work-area-id-desc = Id of Work Area
|
||||
action-park-label = park
|
||||
action-park-desc = Park the Automower® for the given duration (minutes), overriding the schedule
|
||||
action-parkuntilfurthernotice-label = park until further notice
|
||||
action-parkuntilfurthernotice-desc = Parks the automower until the schedule is resumed.
|
||||
action-parkuntilfurthernotice-desc = Park the Automower® until it is started again by the start action/command or the schedule gets resumed
|
||||
action-parkuntilnextschedule-label = park until the next schedule
|
||||
action-parkuntilnextschedule-desc = Parks the automower until the next schedule.
|
||||
action-pause-label = pause the automower
|
||||
action-pause-desc = Pauses the automower wherever it currently is.
|
||||
action-parkuntilnextschedule-desc = Park the Automower®, fully charge it and start afterwards according to the schedule
|
||||
action-pause-label = pause
|
||||
action-pause-desc = Pause the Automower® at the current location until manual resume
|
||||
action-resumeschedule-label = resume the schedule
|
||||
action-resumeschedule-desc = Resumes the schedule for the automower.
|
||||
action-start-label = start the automower
|
||||
action-start-desc = Starts the automower for a defined amount of time, overriding its schedule.
|
||||
action-resumeschedule-desc = Resume the schedule of the Automower®
|
||||
action-start-label = start
|
||||
action-start-desc = Start the Automower® for the given duration (minutes), overriding the schedule
|
||||
action-start-in-work-area-label = start in work area
|
||||
action-start-in-work-area-desc = Start the Automower® in the given Work Area for the given duration (minutes), overriding the schedule
|
||||
action-confirm-error-label = confirm error
|
||||
action-confirm-error-desc = Confirm current non fatal error.
|
||||
action-confirm-error-desc = Confirm current non fatal error
|
||||
action-reset-cutting-blade-usage-time-label = reset cutting blade usage time
|
||||
action-reset-cutting-blade-usage-time-desc = Reset the cutting blade usage time.
|
||||
action-set-settings-label = update automower settings
|
||||
action-set-settings-desc = Sends a set of Settings to the automower.
|
||||
action-reset-cutting-blade-usage-time-desc = Reset the cutting blade usage time
|
||||
action-set-settings-label = update settings
|
||||
action-set-settings-desc = Sends a set of Settings to the Automower®
|
||||
action-input-cutting-height-label = cutting height
|
||||
action-input-cutting-height-desc = Prescaled cutting height, Range: 1-9.
|
||||
action-input-cutting-height-desc = Prescaled cutting height, Range: 1-9
|
||||
action-input-headlight-mode-label = headlight mode
|
||||
action-input-headlight-mode-desc = Headlight Mode (ALWAYS_ON, ALWAYS_OFF, EVENING_ONLY, EVENING_AND_NIGHT).
|
||||
action-input-headlight-mode-desc = Headlight Mode (ALWAYS_ON, ALWAYS_OFF, EVENING_ONLY, EVENING_AND_NIGHT)
|
||||
action-set-work-area-label = update work area configuration
|
||||
action-set-work-area-desc = Update the work area configuration of the specified area.
|
||||
action-input-workarea-id-label = work area id
|
||||
action-input-workarea-id-desc = Id of WorkArea to be updated.
|
||||
action-set-work-area-desc = Update the Work Area configuration
|
||||
action-input-enable-label = enable
|
||||
action-input-enable-desc = Enable or disable WorkArea.
|
||||
action-input-enable-desc = Enable or disable Work Area / stay-out zone
|
||||
action-input-cutting-height-label = cutting height
|
||||
action-input-cutting-height-desc = Cutting height of the WorkArea.
|
||||
action-set-stayoutzone-label = update stayout zone configuration
|
||||
action-set-stayoutzone-desc = Update the stayout zone configuration of the specified zone.
|
||||
action-input-cutting-height-desc = Cutting height of the Work Area, range: 0-100
|
||||
action-set-stayoutzone-label = update stay-out zone configuration
|
||||
action-set-stayoutzone-desc = Update the stay-out zone configuration of the specified zone
|
||||
action-input-zone-id-label = zone id
|
||||
action-input-zone-id-desc = Id of the stayout zone to be updated.
|
||||
action-input-enable-label = enable
|
||||
action-input-enable-desc = Enable or disable stayout zone.
|
||||
action-input-zone-id-desc = Id of the stay-out zone to be updated
|
||||
action-set-calendartask-label = update calendar task configuration
|
||||
action-set-calendartask-desc = Update the calendar task configuration of the mower or specified work area.
|
||||
action-input-workarea-id-label = work area id
|
||||
action-input-workarea-id-desc = Id of WorkArea where the calendar task configuration shall be updated (null if mower doesn't support work areas).
|
||||
action-set-calendartask-desc = Update the calendar task configuration of the Automower® or specified Work Area
|
||||
action-input-start-label = start
|
||||
action-input-start-desc = Start time relative to midnight (minutes).
|
||||
action-input-start-desc = Start time relative to midnight (minutes)
|
||||
action-input-duration-label = duration
|
||||
action-input-duration-desc = Duration time (minutes).
|
||||
action-input-duration-desc = Duration time (minutes)
|
||||
action-input-monday-label = monday[]
|
||||
action-input-monday-desc = Enabled on Mondays (array with the number of calendar tasks).
|
||||
action-input-monday-desc = Enabled on Mondays (array with the number of calendar tasks)
|
||||
action-input-tuesday-label = tuesday[]
|
||||
action-input-tuesday-desc = Enabled on Tuesdays (array with the number of calendar tasks).
|
||||
action-input-tuesday-desc = Enabled on Tuesdays (array with the number of calendar tasks)
|
||||
action-input-wednesday-label = wednesday[]
|
||||
action-input-wednesday-desc = Enabled on Wednesdays (array with the number of calendar tasks).
|
||||
action-input-wednesday-desc = Enabled on Wednesdays (array with the number of calendar tasks)
|
||||
action-input-thursday-label = thursday[]
|
||||
action-input-thursday-desc = Enabled on Thursdays (array with the number of calendar tasks).
|
||||
action-input-thursday-desc = Enabled on Thursdays (array with the number of calendar tasks)
|
||||
action-input-friday-label = friday[]
|
||||
action-input-friday-desc = Enabled on Fridays (array with the number of calendar tasks).
|
||||
action-input-friday-desc = Enabled on Fridays (array with the number of calendar tasks)
|
||||
action-input-saturday-label = saturday
|
||||
action-input-saturday-desc = Enabled on Saturdays (array with the number of calendar tasks).
|
||||
action-input-saturday-desc = Enabled on Saturdays (array with the number of calendar tasks)
|
||||
action-input-sunday-label = sunday
|
||||
action-input-sunday-desc = Enabled on Sunday (array with the number of calendar tasks).
|
||||
action-input-sunday-desc = Enabled on Sunday (array with the number of calendar tasks)
|
||||
action-poll-label = poll
|
||||
action-poll-desc = Poll mower status update from the cloud
|
||||
action-poll-desc = Poll Automower® status update from the cloud
|
||||
|
||||
# status messages
|
||||
|
||||
comm-error-httpclient-init-failed = Unable to initialize http client
|
||||
comm-error-query-mowers-failed = Unable to query registered mowers
|
||||
comm-error-query-mower-failed = Unable to query the automower status
|
||||
comm-error-send-mower-command-failed = Unable to send automower command
|
||||
comm-error-mower-not-connected-to-cloud = Automower not connected to the cloud
|
||||
conf-error-no-app-key = Cannot connect to Automower bridge as no app key is available in the configuration
|
||||
conf-error-no-app-secret = Cannot connect to Automower bridge as no app secret is available in the configuration
|
||||
comm-error-query-mowers-failed = Unable to query registered Automower®
|
||||
comm-error-query-mower-failed = Unable to query the Automower® status
|
||||
comm-error-send-mower-command-failed = Unable to send Automower® command
|
||||
comm-error-mower-not-connected-to-cloud = Automower® not connected to the cloud
|
||||
conf-error-no-app-key = Cannot connect to Automower® bridge as no app key is available in the configuration
|
||||
conf-error-no-app-secret = Cannot connect to Automower® bridge as no app secret is available in the configuration
|
||||
conf-error-invalid-polling-interval = Invalid polling interval specified. The polling interval has to be >= 1
|
||||
conf-error-no-mower-id = No Automower ID specified. Unable to communicate with the mower without an ID
|
||||
conf-error-no-bridge = No valid bridge for the automower is available
|
||||
conf-error-no-mower-id = No Automower® ID specified. Unable to communicate with the Automower® without an ID
|
||||
conf-error-no-bridge = No valid bridge for the Automower® is available
|
||||
|
||||
+99
-111
@@ -6,30 +6,31 @@
|
||||
|
||||
<!-- Automower Bridge Thing Type -->
|
||||
<bridge-type id="bridge">
|
||||
<label>Automower Connect Bridge</label>
|
||||
<description>The bridge to communicate with the Automower Connect API</description>
|
||||
<label>Automower® Connect Bridge</label>
|
||||
<description>The bridge to communicate with the Automower® Connect API</description>
|
||||
<semantic-equipment-tag>WebService</semantic-equipment-tag>
|
||||
|
||||
|
||||
<config-description>
|
||||
<parameter name="appKey" type="text" required="true">
|
||||
<label>Application Key</label>
|
||||
<description>The Application Key is required to communicate with the Automower Connect API at
|
||||
https://developer.husqvarnagroup.cloud/. It can be obtained by
|
||||
registering an Application on the Husqvarna Website.
|
||||
This application also needs to be connected to the
|
||||
"Authentication API" and the "Automower Connect API"</description>
|
||||
<description>The Application Key is required to communicate with the Automower® Connect API.
|
||||
It can be obtained by
|
||||
registering an Application on https://developer.husqvarnagroup.cloud/.
|
||||
This application needs to be connected to the
|
||||
"Authentication API" and the "Automower® Connect
|
||||
API". https://developer.husqvarnagroup.cloud/docs/getting-started
|
||||
</description>
|
||||
</parameter>
|
||||
<parameter name="appSecret" type="text" required="true">
|
||||
<label>Application Secret</label>
|
||||
<description>The Application Secret is required to communicate with the Automower Connect API at
|
||||
https://developer.husqvarnagroup.cloud/. It can be obtained by
|
||||
registering an Application on the Husqvarna Website.</description>
|
||||
<description>The Application Secret is required to communicate with the Automower® Connect API. See "Application
|
||||
Key" for further details</description>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" required="false" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<default>3600</default>
|
||||
<description>How often the available automowers should be queried in seconds</description>
|
||||
<default>300</default>
|
||||
<description>How often the current Automower® states should be polled using REST API</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
@@ -41,7 +42,7 @@
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Automower</label>
|
||||
<label>Automower®</label>
|
||||
<description>An automatic lawn mower</description>
|
||||
<semantic-equipment-tag>LawnMower</semantic-equipment-tag>
|
||||
|
||||
@@ -50,7 +51,6 @@
|
||||
<channel-group id="setting" typeId="settingsType"/>
|
||||
<channel-group id="statistic" typeId="statisticsType"/>
|
||||
<channel-group id="calendartask" typeId="calendarTasksType"/>
|
||||
<channel-group id="position" typeId="positionsType"/>
|
||||
<channel-group id="stayoutzone" typeId="stayoutZonesType"/>
|
||||
<channel-group id="workarea" typeId="workAreasType"/>
|
||||
<channel-group id="command" typeId="commandsType"/>
|
||||
@@ -67,22 +67,18 @@
|
||||
<property name="mowerHasPosition">N/A</property>
|
||||
<property name="mowerHasStayOutZones">N/A</property>
|
||||
<property name="mowerHasWorkAreas">N/A</property>
|
||||
<property name="thingTypeVersion">1</property>
|
||||
<property name="thingTypeVersion">2</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="mowerId" type="text" required="true">
|
||||
<label>Automower Id</label>
|
||||
<description>The Id of an automower as used by the Automower Connect Api to identify a mower</description>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" required="false" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<default>600</default>
|
||||
<description>How often the current automower state should be polled in seconds</description>
|
||||
<label>Automower® Id</label>
|
||||
<description>The Id of an Automower® as used by the Automower® Connect API to identify a Automower®. This is
|
||||
automatically filled when the thing is discovered.</description>
|
||||
</parameter>
|
||||
<parameter name="mowerZoneId" type="text" required="false">
|
||||
<label>TimeZone</label>
|
||||
<description>Time zone of the mower (e.g. Europe/Berlin)</description>
|
||||
<description>Time zone of the Automower® (e.g. Europe/Berlin). Default is the time zone configured in openHAB</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
@@ -114,6 +110,9 @@
|
||||
<channel id="override-action" typeId="overrideActionType"/>
|
||||
<channel id="restricted-reason" typeId="restrictedReasonType"/>
|
||||
<channel id="external-reason" typeId="externalReasonType"/>
|
||||
<!-- channels created on demand
|
||||
<channel id="position" typeId="positionType"/>
|
||||
-->
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
@@ -168,18 +167,6 @@
|
||||
-->
|
||||
</channel-group-type>
|
||||
|
||||
<!-- Positions -->
|
||||
<channel-group-type id="positionsType">
|
||||
<label>Positions</label>
|
||||
<!-- channels created on demand
|
||||
<channels>
|
||||
<channel id="last" typeId="lastPositionType"/>
|
||||
<channel id="<xx>" typeId="positionType"/>
|
||||
...
|
||||
</channels>
|
||||
-->
|
||||
</channel-group-type>
|
||||
|
||||
<!-- Stayout Zones -->
|
||||
<channel-group-type id="stayoutZonesType">
|
||||
<label>Stayout Zones</label>
|
||||
@@ -213,16 +200,13 @@
|
||||
<!-- Messages -->
|
||||
<channel-group-type id="messagesType">
|
||||
<label>Messages</label>
|
||||
<!-- channels created dynamically (1...50)
|
||||
<channels>
|
||||
<channel id="<xx>-time" typeId="messageTimeType"/>
|
||||
<channel id="<xx>-code" typeId="messageCodeType"/>
|
||||
<channel id="<xx>-text" typeId="messageType"/>
|
||||
<channel id="<xx>-severity" typeId="messageSeverityType"/>
|
||||
<channel id="<xx>-position" typeId="messagePositionType"/>
|
||||
...
|
||||
</channels>
|
||||
-->
|
||||
<channels>
|
||||
<channel id="msg-timestamp" typeId="messageTimeType"/>
|
||||
<channel id="msg-code" typeId="messageCodeType"/>
|
||||
<channel id="msg-text" typeId="messageType"/>
|
||||
<channel id="msg-severity" typeId="messageSeverityType"/>
|
||||
<channel id="msg-gps-position" typeId="messagePositionType"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<!-- Commands -->
|
||||
@@ -230,6 +214,7 @@
|
||||
<label>Commands</label>
|
||||
<channels>
|
||||
<channel id="start" typeId="start"/>
|
||||
<channel id="start_in_work_area" typeId="startInWorkArea"/>
|
||||
<channel id="resume_schedule" typeId="resumeSchedule"/>
|
||||
<channel id="pause" typeId="pause"/>
|
||||
<channel id="park" typeId="park"/>
|
||||
@@ -240,8 +225,8 @@
|
||||
|
||||
<channel-type id="nameType">
|
||||
<item-type>String</item-type>
|
||||
<label>Automower Name</label>
|
||||
<description>The channel providing the automower name</description>
|
||||
<label>Automower® Name</label>
|
||||
<description>The name of the Automower®</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@@ -285,7 +270,7 @@
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="NONE">No inactive reason</option>
|
||||
<option value="PLANNING">The mower is planning a path or a work area</option>
|
||||
<option value="PLANNING">The Automower® is planning a path or a Work Area</option>
|
||||
<option value="SEARCHING_FOR_SATELLITES">Waiting for fix when using EPOS</option>
|
||||
</options>
|
||||
</state>
|
||||
@@ -302,7 +287,7 @@
|
||||
<option value="PAUSED">Paused by user</option>
|
||||
<option value="IN_OPERATION">Working</option>
|
||||
<option value="WAIT_UPDATING">Downloading new firmware</option>
|
||||
<option value="WAIT_POWER_UP">Booting mower</option>
|
||||
<option value="WAIT_POWER_UP">Booting Automower®</option>
|
||||
<option value="RESTRICTED_NONE">No restricted reason</option>
|
||||
<option value="RESTRICTED_WEEK_SCHEDULE">Restricted by week schedule</option>
|
||||
<option value="RESTRICTED_PARK_OVERRIDE">Forced to park</option>
|
||||
@@ -310,7 +295,7 @@
|
||||
<option value="RESTRICTED_DAILY_LIMIT">Restricted by daily limit</option>
|
||||
<option value="RESTRICTED_FOTA">Restricted by FOTA transfer</option>
|
||||
<option value="RESTRICTED_FROST">Restricted by frost sensor</option>
|
||||
<option value="RESTRICTED_ALL_WORK_AREAS_COMPLETED">Restricted: All work areas completed</option>
|
||||
<option value="RESTRICTED_ALL_WORK_AREAS_COMPLETED">Restricted: All Work Areas completed</option>
|
||||
<option value="RESTRICTED_EXTERNAL">Restricted by external reason</option>
|
||||
<option value="OFF">Off</option>
|
||||
<option value="STOPPED">Stopped: Manual intervention required</option>
|
||||
@@ -324,21 +309,21 @@
|
||||
<channel-type id="workAreaIdType" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Work Area Id</label>
|
||||
<description>Id of the active work area</description>
|
||||
<description>Id of the active Work Area</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workAreaType">
|
||||
<item-type>String</item-type>
|
||||
<label>Work Area Name</label>
|
||||
<description>Name of the active work area</description>
|
||||
<description>Name of the active Work Area</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lastUpdateType">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Update</label>
|
||||
<description>The time when the mower sent the last update</description>
|
||||
<description>The time when the Automower® sent the last update</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@@ -352,13 +337,13 @@
|
||||
<channel-type id="pollUpdateType" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Poll Update</label>
|
||||
<description>Poll mower status update from the cloud</description>
|
||||
<description>Poll Automower® status update from the cloud</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="batteryType">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Battery</label>
|
||||
<description>The battery level of the mower at the time of last update</description>
|
||||
<description>The battery state of charge in percent</description>
|
||||
<tags>
|
||||
<tag>Measurement</tag>
|
||||
<tag>Energy</tag>
|
||||
@@ -369,48 +354,50 @@
|
||||
<channel-type id="errorCodeType" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Error Code</label>
|
||||
<description>The error code at the time of last update</description>
|
||||
<description>The current error code</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorMessageType">
|
||||
<item-type>String</item-type>
|
||||
<label>Error Message</label>
|
||||
<description>The error message at the time of last update</description>
|
||||
<description>The current error message</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorTimestampType">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Error Time</label>
|
||||
<description>The time when the error occurred</description>
|
||||
<description>The time when the current error occurred</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="errorConfirmableType" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Error Confirmable</label>
|
||||
<description>If the mower has an Error Code this attribute states if the error is confirmable</description>
|
||||
<description>If the Automower® has an error, this attribute states if the error is confirmable</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nextStartType">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Next Auto Start</label>
|
||||
<description>The channel providing the time for the next auto start. If the mower is charging then the value is the
|
||||
estimated time when it will be leaving the charging station. If the mower is about to start now, the value is NULL.</description>
|
||||
<label>Next Start</label>
|
||||
<description>The time for the next scheduled start.
|
||||
If the Automower® is charging then the value is the estimated time
|
||||
when it will be leaving the charging station.
|
||||
If the Automower® is about to start now, the value is NULL</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="overrideActionType">
|
||||
<item-type>String</item-type>
|
||||
<label>Override Action</label>
|
||||
<description>The channel providing an action that overrides current planner operation.</description>
|
||||
<description>The action that overrides the current planner operation</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="restrictedReasonType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Restricted Reason</label>
|
||||
<description>The channel providing a reason that restrics current planner operation.</description>
|
||||
<description>The reason that restrics the current planner operation</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="NONE">No restricted reason</option>
|
||||
@@ -420,7 +407,7 @@
|
||||
<option value="DAILY_LIMIT">Restricted by daily limit</option>
|
||||
<option value="FOTA">Restricted by FOTA transfer</option>
|
||||
<option value="FROST">Restricted by frost sensor</option>
|
||||
<option value="ALL_WORK_AREAS_COMPLETED">Restricted: All work areas completed</option>
|
||||
<option value="ALL_WORK_AREAS_COMPLETED">Restricted: All Work Areas completed</option>
|
||||
<option value="EXTERNAL">Restricted by external reason</option>
|
||||
</options>
|
||||
</state>
|
||||
@@ -429,7 +416,15 @@
|
||||
<channel-type id="externalReasonType" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>External Reason</label>
|
||||
<description>The channel providing an external reason that restrics current planner operation.</description>
|
||||
<description>An external reason set by i.e. Google Assistant or Amazon Alexa that restrics the current planner
|
||||
operation</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="positionType" advanced="false">
|
||||
<item-type>Location</item-type>
|
||||
<label>Last GPS Position</label>
|
||||
<description>Last GPS position of the Automower®</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@@ -442,7 +437,6 @@
|
||||
<channel-type id="settingHeadlightModeType">
|
||||
<item-type>String</item-type>
|
||||
<label>Headlight Mode</label>
|
||||
<description>Information about headlights</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="statCuttingBladeUsageTimeType">
|
||||
@@ -455,8 +449,8 @@
|
||||
<channel-type id="statDownTimeType" advanced="true">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Down Time</label>
|
||||
<description>The time the mower has been disconnected from the cloud</description>
|
||||
<state readOnly="true" pattern="%1$tHh:%1$tMm:%1$tSs"/>
|
||||
<description>The time the Automower® has been disconnected from the cloud</description>
|
||||
<state readOnly="true" pattern="%1$tdd:%1$tHh:%1$tMm:%1$tSs"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="statNumberOfChargingCyclesType">
|
||||
@@ -469,7 +463,7 @@
|
||||
<channel-type id="statNumberOfCollisionsType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Number of Collisions</label>
|
||||
<description>The total number of collisions</description>
|
||||
<description>Total number of collisions</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@@ -525,22 +519,8 @@
|
||||
<channel-type id="statUpTimeType" advanced="true">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Up Time</label>
|
||||
<description>The time the mower has been connected to the cloud</description>
|
||||
<state readOnly="true" pattern="%1$tHh:%1$tMm:%1$tSs"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lastPositionType" advanced="false">
|
||||
<item-type>Location</item-type>
|
||||
<label>Last GPS Position</label>
|
||||
<description>Last GPS position of the mower</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="positionType" advanced="true">
|
||||
<item-type>Location</item-type>
|
||||
<label>GPS Position</label>
|
||||
<description>A waypoint of the mower's activity</description>
|
||||
<state readOnly="true"/>
|
||||
<description>The time the Automower® has been connected to the cloud</description>
|
||||
<state readOnly="true" pattern="%1$tdd:%1$tHh:%1$tMm:%1$tSs"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Calendar Tasks -->
|
||||
@@ -603,28 +583,28 @@
|
||||
<item-type>Switch</item-type>
|
||||
<label>Stayout Zones Dirty Flag</label>
|
||||
<description>If the stay-out zones are synchronized with the Husqvarna cloud. If the map is dirty you can not enable
|
||||
or disable a stay-out zone.</description>
|
||||
or disable a stay-out zone</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zoneIdType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Stayout Zone Id</label>
|
||||
<description>Id of the Stayout zone</description>
|
||||
<description>Id of the stay-out zone</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zoneNameType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Stayout Zone Name</label>
|
||||
<description>The name of the Stayout zone</description>
|
||||
<description>The name of the stay-out zone</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zoneEnabledType" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Stayout Zone Enabled</label>
|
||||
<description>If the Stayout zone is enabled, the Automower® will not access the zone</description>
|
||||
<description>If the stay-out zone is enabled, the Automower® will not access the zone</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- Work Areas -->
|
||||
@@ -638,70 +618,70 @@
|
||||
<channel-type id="workareaNameType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Work Area Name</label>
|
||||
<description>Name of the work area</description>
|
||||
<description>Name of the Work Area</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workareaCuttingHeightType" advanced="true">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Cutting Height</label>
|
||||
<description>Cutting height of the work area, range: 0-100</description>
|
||||
<description>Cutting height of the Work Area, range: 0-100</description>
|
||||
<state pattern="%d %%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workareaEnabledType" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Work Area Enabled</label>
|
||||
<description>If the work area is enabled or disabled</description>
|
||||
<description>If the Work Area is enabled or disabled</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workareaProgressType" advanced="true">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Work Area Progress</label>
|
||||
<description>The progress on a work area. EPOS mowers and systematic mowing work areas only.</description>
|
||||
<description>The progress on a Work Area. EPOS Automower® and systematic mowing Work Areas only</description>
|
||||
<state readOnly="true" pattern="%d %%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workareaLastTimeCompletedType" advanced="true">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Last Time Completed</label>
|
||||
<description>Timestamp when the work area was last completed. EPOS mowers and systematic mowing work areas only.</description>
|
||||
<description>Timestamp when the Work Area was last completed. EPOS Automower® and systematic mowing Work Areas only</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<!-- Messages -->
|
||||
<channel-type id="messageTimeType" advanced="true">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Timestamp</label>
|
||||
<description>Timestamp when the event occurred</description>
|
||||
<label>Last Error Time</label>
|
||||
<description>The time when the last error occurred</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="messageCodeType" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Code</label>
|
||||
<description>(Error) code of the event</description>
|
||||
<label>Last Error Code</label>
|
||||
<description>The last error code</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="messageType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Message</label>
|
||||
<description>The Message</description>
|
||||
<label>Last Error Message</label>
|
||||
<description>The last error message</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="messageSeverityType" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Severity</label>
|
||||
<description>The severity of the event</description>
|
||||
<label>Message Severity</label>
|
||||
<description>The severity of the last error</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="messagePositionType" advanced="true">
|
||||
<item-type>Location</item-type>
|
||||
<label>GPS Position</label>
|
||||
<description>GPS Position of the event (if available)</description>
|
||||
<label>Message GPS Position</label>
|
||||
<description>GPS position of the last event (if available)</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
@@ -709,38 +689,46 @@
|
||||
<channel-type id="start">
|
||||
<item-type>Number</item-type>
|
||||
<label>Start with Duration</label>
|
||||
<description>Start for a duration in minutes</description>
|
||||
<description>Start the Automower® for the given duration, overriding the schedule</description>
|
||||
<state pattern="%d min" min="1" max="1440" step="1"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="startInWorkArea">
|
||||
<item-type>Number</item-type>
|
||||
<label>Start in Work Area</label>
|
||||
<description>Start the Automower® in the given Work Area, overriding the schedule. The Automower® will continue
|
||||
forever</description>
|
||||
<state pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="resumeSchedule">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Resume Schedule</label>
|
||||
<description>Resume schedule</description>
|
||||
<description>Resume the schedule of the Automower®</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pause">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Pause</label>
|
||||
<description>Pause the mower now until manual resume</description>
|
||||
<description>Pause the Automower® at the current location until manual resume</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="park">
|
||||
<item-type>Number</item-type>
|
||||
<label>Park with Duration</label>
|
||||
<description>Park for a duration in minutes</description>
|
||||
<description>Park the Automower® for the given duration, overriding the schedule</description>
|
||||
<state pattern="%d min" min="1" max="1440" step="1"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="parkUntilNextSchedule">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Park Until Next Schedule</label>
|
||||
<description>Park until next schedule</description>
|
||||
<description>Park the Automower®, fully charge it and start afterwards according to the schedule</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="parkUntilFurtherNotice">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Park and Pause the Schedule</label>
|
||||
<description>Park and pause the mower schedule until manual resume</description>
|
||||
<description>Park the Automower® until it is started again by the start action/command or the schedule gets resumed</description>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
|
||||
@@ -158,24 +158,352 @@
|
||||
<remove-channel id="position50"/>
|
||||
|
||||
<!-- Commands -->
|
||||
<update-channel id="start" groupIds="commands">
|
||||
<update-channel id="start" groupIds="command">
|
||||
<type>automower:start</type>
|
||||
</update-channel>
|
||||
<update-channel id="resume_schedule" groupIds="commands">
|
||||
<update-channel id="resume_schedule" groupIds="command">
|
||||
<type>automower:resumeSchedule</type>
|
||||
</update-channel>
|
||||
<update-channel id="pause" groupIds="commands">
|
||||
<update-channel id="pause" groupIds="command">
|
||||
<type>automower:pause</type>
|
||||
</update-channel>
|
||||
<update-channel id="park" groupIds="commands">
|
||||
<update-channel id="park" groupIds="command">
|
||||
<type>automower:park</type>
|
||||
</update-channel>
|
||||
<update-channel id="park_until_next_schedule" groupIds="commands">
|
||||
<update-channel id="park_until_next_schedule" groupIds="command">
|
||||
<type>automower:parkUntilNextSchedule</type>
|
||||
</update-channel>
|
||||
<update-channel id="park_until_further_notice" groupIds="commands">
|
||||
<update-channel id="park_until_further_notice" groupIds="command">
|
||||
<type>automower:parkUntilFurtherNotice</type>
|
||||
</update-channel>
|
||||
</instruction-set>
|
||||
|
||||
<instruction-set targetVersion="2">
|
||||
<!-- Positions -->
|
||||
<remove-channel id="position#last"/>
|
||||
<remove-channel id="position#01-pos"/>
|
||||
<remove-channel id="position#02-pos"/>
|
||||
<remove-channel id="position#03-pos"/>
|
||||
<remove-channel id="position#04-pos"/>
|
||||
<remove-channel id="position#05-pos"/>
|
||||
<remove-channel id="position#06-pos"/>
|
||||
<remove-channel id="position#07-pos"/>
|
||||
<remove-channel id="position#08-pos"/>
|
||||
<remove-channel id="position#09-pos"/>
|
||||
<remove-channel id="position#10-pos"/>
|
||||
<remove-channel id="position#11-pos"/>
|
||||
<remove-channel id="position#12-pos"/>
|
||||
<remove-channel id="position#13-pos"/>
|
||||
<remove-channel id="position#14-pos"/>
|
||||
<remove-channel id="position#15-pos"/>
|
||||
<remove-channel id="position#16-pos"/>
|
||||
<remove-channel id="position#17-pos"/>
|
||||
<remove-channel id="position#18-pos"/>
|
||||
<remove-channel id="position#19-pos"/>
|
||||
<remove-channel id="position#20-pos"/>
|
||||
<remove-channel id="position#21-pos"/>
|
||||
<remove-channel id="position#22-pos"/>
|
||||
<remove-channel id="position#23-pos"/>
|
||||
<remove-channel id="position#24-pos"/>
|
||||
<remove-channel id="position#25-pos"/>
|
||||
<remove-channel id="position#26-pos"/>
|
||||
<remove-channel id="position#27-pos"/>
|
||||
<remove-channel id="position#28-pos"/>
|
||||
<remove-channel id="position#29-pos"/>
|
||||
<remove-channel id="position#30-pos"/>
|
||||
<remove-channel id="position#31-pos"/>
|
||||
<remove-channel id="position#32-pos"/>
|
||||
<remove-channel id="position#33-pos"/>
|
||||
<remove-channel id="position#34-pos"/>
|
||||
<remove-channel id="position#35-pos"/>
|
||||
<remove-channel id="position#36-pos"/>
|
||||
<remove-channel id="position#37-pos"/>
|
||||
<remove-channel id="position#38-pos"/>
|
||||
<remove-channel id="position#39-pos"/>
|
||||
<remove-channel id="position#40-pos"/>
|
||||
<remove-channel id="position#41-pos"/>
|
||||
<remove-channel id="position#42-pos"/>
|
||||
<remove-channel id="position#43-pos"/>
|
||||
<remove-channel id="position#44-pos"/>
|
||||
<remove-channel id="position#45-pos"/>
|
||||
<remove-channel id="position#46-pos"/>
|
||||
<remove-channel id="position#47-pos"/>
|
||||
<remove-channel id="position#48-pos"/>
|
||||
<remove-channel id="position#49-pos"/>
|
||||
<remove-channel id="position#50-pos"/>
|
||||
|
||||
<!-- Messages -->
|
||||
<remove-channel id="message#01-msg-timestamp"/>
|
||||
<remove-channel id="message#01-msg-code"/>
|
||||
<remove-channel id="message#01-msg-text"/>
|
||||
<remove-channel id="message#01-msg-severity"/>
|
||||
<remove-channel id="message#01-msg-gps-position"/>
|
||||
<remove-channel id="message#02-msg-timestamp"/>
|
||||
<remove-channel id="message#02-msg-code"/>
|
||||
<remove-channel id="message#02-msg-text"/>
|
||||
<remove-channel id="message#02-msg-severity"/>
|
||||
<remove-channel id="message#02-msg-gps-position"/>
|
||||
<remove-channel id="message#03-msg-timestamp"/>
|
||||
<remove-channel id="message#03-msg-code"/>
|
||||
<remove-channel id="message#03-msg-text"/>
|
||||
<remove-channel id="message#03-msg-severity"/>
|
||||
<remove-channel id="message#03-msg-gps-position"/>
|
||||
<remove-channel id="message#04-msg-timestamp"/>
|
||||
<remove-channel id="message#04-msg-code"/>
|
||||
<remove-channel id="message#04-msg-text"/>
|
||||
<remove-channel id="message#04-msg-severity"/>
|
||||
<remove-channel id="message#04-msg-gps-position"/>
|
||||
<remove-channel id="message#05-msg-timestamp"/>
|
||||
<remove-channel id="message#05-msg-code"/>
|
||||
<remove-channel id="message#05-msg-text"/>
|
||||
<remove-channel id="message#05-msg-severity"/>
|
||||
<remove-channel id="message#05-msg-gps-position"/>
|
||||
<remove-channel id="message#06-msg-timestamp"/>
|
||||
<remove-channel id="message#06-msg-code"/>
|
||||
<remove-channel id="message#06-msg-text"/>
|
||||
<remove-channel id="message#06-msg-severity"/>
|
||||
<remove-channel id="message#06-msg-gps-position"/>
|
||||
<remove-channel id="message#07-msg-timestamp"/>
|
||||
<remove-channel id="message#07-msg-code"/>
|
||||
<remove-channel id="message#07-msg-text"/>
|
||||
<remove-channel id="message#07-msg-severity"/>
|
||||
<remove-channel id="message#07-msg-gps-position"/>
|
||||
<remove-channel id="message#08-msg-timestamp"/>
|
||||
<remove-channel id="message#08-msg-code"/>
|
||||
<remove-channel id="message#08-msg-text"/>
|
||||
<remove-channel id="message#08-msg-severity"/>
|
||||
<remove-channel id="message#08-msg-gps-position"/>
|
||||
<remove-channel id="message#09-msg-timestamp"/>
|
||||
<remove-channel id="message#09-msg-code"/>
|
||||
<remove-channel id="message#09-msg-text"/>
|
||||
<remove-channel id="message#09-msg-severity"/>
|
||||
<remove-channel id="message#09-msg-gps-position"/>
|
||||
<remove-channel id="message#10-msg-timestamp"/>
|
||||
<remove-channel id="message#10-msg-code"/>
|
||||
<remove-channel id="message#10-msg-text"/>
|
||||
<remove-channel id="message#10-msg-severity"/>
|
||||
<remove-channel id="message#10-msg-gps-position"/>
|
||||
<remove-channel id="message#11-msg-timestamp"/>
|
||||
<remove-channel id="message#11-msg-code"/>
|
||||
<remove-channel id="message#11-msg-text"/>
|
||||
<remove-channel id="message#11-msg-severity"/>
|
||||
<remove-channel id="message#11-msg-gps-position"/>
|
||||
<remove-channel id="message#12-msg-timestamp"/>
|
||||
<remove-channel id="message#12-msg-code"/>
|
||||
<remove-channel id="message#12-msg-text"/>
|
||||
<remove-channel id="message#12-msg-severity"/>
|
||||
<remove-channel id="message#12-msg-gps-position"/>
|
||||
<remove-channel id="message#13-msg-timestamp"/>
|
||||
<remove-channel id="message#13-msg-code"/>
|
||||
<remove-channel id="message#13-msg-text"/>
|
||||
<remove-channel id="message#13-msg-severity"/>
|
||||
<remove-channel id="message#13-msg-gps-position"/>
|
||||
<remove-channel id="message#14-msg-timestamp"/>
|
||||
<remove-channel id="message#14-msg-code"/>
|
||||
<remove-channel id="message#14-msg-text"/>
|
||||
<remove-channel id="message#14-msg-severity"/>
|
||||
<remove-channel id="message#14-msg-gps-position"/>
|
||||
<remove-channel id="message#15-msg-timestamp"/>
|
||||
<remove-channel id="message#15-msg-code"/>
|
||||
<remove-channel id="message#15-msg-text"/>
|
||||
<remove-channel id="message#15-msg-severity"/>
|
||||
<remove-channel id="message#15-msg-gps-position"/>
|
||||
<remove-channel id="message#16-msg-timestamp"/>
|
||||
<remove-channel id="message#16-msg-code"/>
|
||||
<remove-channel id="message#16-msg-text"/>
|
||||
<remove-channel id="message#16-msg-severity"/>
|
||||
<remove-channel id="message#16-msg-gps-position"/>
|
||||
<remove-channel id="message#17-msg-timestamp"/>
|
||||
<remove-channel id="message#17-msg-code"/>
|
||||
<remove-channel id="message#17-msg-text"/>
|
||||
<remove-channel id="message#17-msg-severity"/>
|
||||
<remove-channel id="message#17-msg-gps-position"/>
|
||||
<remove-channel id="message#18-msg-timestamp"/>
|
||||
<remove-channel id="message#18-msg-code"/>
|
||||
<remove-channel id="message#18-msg-text"/>
|
||||
<remove-channel id="message#18-msg-severity"/>
|
||||
<remove-channel id="message#18-msg-gps-position"/>
|
||||
<remove-channel id="message#19-msg-timestamp"/>
|
||||
<remove-channel id="message#19-msg-code"/>
|
||||
<remove-channel id="message#19-msg-text"/>
|
||||
<remove-channel id="message#19-msg-severity"/>
|
||||
<remove-channel id="message#19-msg-gps-position"/>
|
||||
<remove-channel id="message#20-msg-timestamp"/>
|
||||
<remove-channel id="message#20-msg-code"/>
|
||||
<remove-channel id="message#20-msg-text"/>
|
||||
<remove-channel id="message#20-msg-severity"/>
|
||||
<remove-channel id="message#20-msg-gps-position"/>
|
||||
<remove-channel id="message#21-msg-timestamp"/>
|
||||
<remove-channel id="message#21-msg-code"/>
|
||||
<remove-channel id="message#21-msg-text"/>
|
||||
<remove-channel id="message#21-msg-severity"/>
|
||||
<remove-channel id="message#21-msg-gps-position"/>
|
||||
<remove-channel id="message#22-msg-timestamp"/>
|
||||
<remove-channel id="message#22-msg-code"/>
|
||||
<remove-channel id="message#22-msg-text"/>
|
||||
<remove-channel id="message#22-msg-severity"/>
|
||||
<remove-channel id="message#22-msg-gps-position"/>
|
||||
<remove-channel id="message#23-msg-timestamp"/>
|
||||
<remove-channel id="message#23-msg-code"/>
|
||||
<remove-channel id="message#23-msg-text"/>
|
||||
<remove-channel id="message#23-msg-severity"/>
|
||||
<remove-channel id="message#23-msg-gps-position"/>
|
||||
<remove-channel id="message#24-msg-timestamp"/>
|
||||
<remove-channel id="message#24-msg-code"/>
|
||||
<remove-channel id="message#24-msg-text"/>
|
||||
<remove-channel id="message#24-msg-severity"/>
|
||||
<remove-channel id="message#24-msg-gps-position"/>
|
||||
<remove-channel id="message#25-msg-timestamp"/>
|
||||
<remove-channel id="message#25-msg-code"/>
|
||||
<remove-channel id="message#25-msg-text"/>
|
||||
<remove-channel id="message#25-msg-severity"/>
|
||||
<remove-channel id="message#25-msg-gps-position"/>
|
||||
<remove-channel id="message#26-msg-timestamp"/>
|
||||
<remove-channel id="message#26-msg-code"/>
|
||||
<remove-channel id="message#26-msg-text"/>
|
||||
<remove-channel id="message#26-msg-severity"/>
|
||||
<remove-channel id="message#26-msg-gps-position"/>
|
||||
<remove-channel id="message#27-msg-timestamp"/>
|
||||
<remove-channel id="message#27-msg-code"/>
|
||||
<remove-channel id="message#27-msg-text"/>
|
||||
<remove-channel id="message#27-msg-severity"/>
|
||||
<remove-channel id="message#27-msg-gps-position"/>
|
||||
<remove-channel id="message#28-msg-timestamp"/>
|
||||
<remove-channel id="message#28-msg-code"/>
|
||||
<remove-channel id="message#28-msg-text"/>
|
||||
<remove-channel id="message#28-msg-severity"/>
|
||||
<remove-channel id="message#28-msg-gps-position"/>
|
||||
<remove-channel id="message#29-msg-timestamp"/>
|
||||
<remove-channel id="message#29-msg-code"/>
|
||||
<remove-channel id="message#29-msg-text"/>
|
||||
<remove-channel id="message#29-msg-severity"/>
|
||||
<remove-channel id="message#29-msg-gps-position"/>
|
||||
<remove-channel id="message#30-msg-timestamp"/>
|
||||
<remove-channel id="message#30-msg-code"/>
|
||||
<remove-channel id="message#30-msg-text"/>
|
||||
<remove-channel id="message#30-msg-severity"/>
|
||||
<remove-channel id="message#30-msg-gps-position"/>
|
||||
<remove-channel id="message#31-msg-timestamp"/>
|
||||
<remove-channel id="message#31-msg-code"/>
|
||||
<remove-channel id="message#31-msg-text"/>
|
||||
<remove-channel id="message#31-msg-severity"/>
|
||||
<remove-channel id="message#31-msg-gps-position"/>
|
||||
<remove-channel id="message#32-msg-timestamp"/>
|
||||
<remove-channel id="message#32-msg-code"/>
|
||||
<remove-channel id="message#32-msg-text"/>
|
||||
<remove-channel id="message#32-msg-severity"/>
|
||||
<remove-channel id="message#32-msg-gps-position"/>
|
||||
<remove-channel id="message#33-msg-timestamp"/>
|
||||
<remove-channel id="message#33-msg-code"/>
|
||||
<remove-channel id="message#33-msg-text"/>
|
||||
<remove-channel id="message#33-msg-severity"/>
|
||||
<remove-channel id="message#33-msg-gps-position"/>
|
||||
<remove-channel id="message#34-msg-timestamp"/>
|
||||
<remove-channel id="message#34-msg-code"/>
|
||||
<remove-channel id="message#34-msg-text"/>
|
||||
<remove-channel id="message#34-msg-severity"/>
|
||||
<remove-channel id="message#34-msg-gps-position"/>
|
||||
<remove-channel id="message#35-msg-timestamp"/>
|
||||
<remove-channel id="message#35-msg-code"/>
|
||||
<remove-channel id="message#35-msg-text"/>
|
||||
<remove-channel id="message#35-msg-severity"/>
|
||||
<remove-channel id="message#35-msg-gps-position"/>
|
||||
<remove-channel id="message#36-msg-timestamp"/>
|
||||
<remove-channel id="message#36-msg-code"/>
|
||||
<remove-channel id="message#36-msg-text"/>
|
||||
<remove-channel id="message#36-msg-severity"/>
|
||||
<remove-channel id="message#36-msg-gps-position"/>
|
||||
<remove-channel id="message#37-msg-timestamp"/>
|
||||
<remove-channel id="message#37-msg-code"/>
|
||||
<remove-channel id="message#37-msg-text"/>
|
||||
<remove-channel id="message#37-msg-severity"/>
|
||||
<remove-channel id="message#37-msg-gps-position"/>
|
||||
<remove-channel id="message#38-msg-timestamp"/>
|
||||
<remove-channel id="message#38-msg-code"/>
|
||||
<remove-channel id="message#38-msg-text"/>
|
||||
<remove-channel id="message#38-msg-severity"/>
|
||||
<remove-channel id="message#38-msg-gps-position"/>
|
||||
<remove-channel id="message#39-msg-timestamp"/>
|
||||
<remove-channel id="message#39-msg-code"/>
|
||||
<remove-channel id="message#39-msg-text"/>
|
||||
<remove-channel id="message#39-msg-severity"/>
|
||||
<remove-channel id="message#39-msg-gps-position"/>
|
||||
<remove-channel id="message#40-msg-timestamp"/>
|
||||
<remove-channel id="message#40-msg-code"/>
|
||||
<remove-channel id="message#40-msg-text"/>
|
||||
<remove-channel id="message#40-msg-severity"/>
|
||||
<remove-channel id="message#40-msg-gps-position"/>
|
||||
<remove-channel id="message#41-msg-timestamp"/>
|
||||
<remove-channel id="message#41-msg-code"/>
|
||||
<remove-channel id="message#41-msg-text"/>
|
||||
<remove-channel id="message#41-msg-severity"/>
|
||||
<remove-channel id="message#41-msg-gps-position"/>
|
||||
<remove-channel id="message#42-msg-timestamp"/>
|
||||
<remove-channel id="message#42-msg-code"/>
|
||||
<remove-channel id="message#42-msg-text"/>
|
||||
<remove-channel id="message#42-msg-severity"/>
|
||||
<remove-channel id="message#42-msg-gps-position"/>
|
||||
<remove-channel id="message#43-msg-timestamp"/>
|
||||
<remove-channel id="message#43-msg-code"/>
|
||||
<remove-channel id="message#43-msg-text"/>
|
||||
<remove-channel id="message#43-msg-severity"/>
|
||||
<remove-channel id="message#43-msg-gps-position"/>
|
||||
<remove-channel id="message#44-msg-timestamp"/>
|
||||
<remove-channel id="message#44-msg-code"/>
|
||||
<remove-channel id="message#44-msg-text"/>
|
||||
<remove-channel id="message#44-msg-severity"/>
|
||||
<remove-channel id="message#44-msg-gps-position"/>
|
||||
<remove-channel id="message#45-msg-timestamp"/>
|
||||
<remove-channel id="message#45-msg-code"/>
|
||||
<remove-channel id="message#45-msg-text"/>
|
||||
<remove-channel id="message#45-msg-severity"/>
|
||||
<remove-channel id="message#45-msg-gps-position"/>
|
||||
<remove-channel id="message#46-msg-timestamp"/>
|
||||
<remove-channel id="message#46-msg-code"/>
|
||||
<remove-channel id="message#46-msg-text"/>
|
||||
<remove-channel id="message#46-msg-severity"/>
|
||||
<remove-channel id="message#46-msg-gps-position"/>
|
||||
<remove-channel id="message#47-msg-timestamp"/>
|
||||
<remove-channel id="message#47-msg-code"/>
|
||||
<remove-channel id="message#47-msg-text"/>
|
||||
<remove-channel id="message#47-msg-severity"/>
|
||||
<remove-channel id="message#47-msg-gps-position"/>
|
||||
<remove-channel id="message#48-msg-timestamp"/>
|
||||
<remove-channel id="message#48-msg-code"/>
|
||||
<remove-channel id="message#48-msg-text"/>
|
||||
<remove-channel id="message#48-msg-severity"/>
|
||||
<remove-channel id="message#48-msg-gps-position"/>
|
||||
<remove-channel id="message#49-msg-timestamp"/>
|
||||
<remove-channel id="message#49-msg-code"/>
|
||||
<remove-channel id="message#49-msg-text"/>
|
||||
<remove-channel id="message#49-msg-severity"/>
|
||||
<remove-channel id="message#49-msg-gps-position"/>
|
||||
<remove-channel id="message#50-msg-timestamp"/>
|
||||
<remove-channel id="message#50-msg-code"/>
|
||||
<remove-channel id="message#50-msg-text"/>
|
||||
<remove-channel id="message#50-msg-severity"/>
|
||||
<remove-channel id="message#50-msg-gps-position"/>
|
||||
|
||||
<add-channel id="msg-timestamp" groupIds="message">
|
||||
<type>automower:messageTimeType</type>
|
||||
</add-channel>
|
||||
<add-channel id="msg-code" groupIds="message">
|
||||
<type>automower:messageCodeType</type>
|
||||
</add-channel>
|
||||
<add-channel id="msg-text" groupIds="message">
|
||||
<type>automower:messageType</type>
|
||||
</add-channel>
|
||||
<add-channel id="msg-severity" groupIds="message">
|
||||
<type>automower:messageSeverityType</type>
|
||||
</add-channel>
|
||||
<add-channel id="msg-gps-position" groupIds="message">
|
||||
<type>automower:messagePositionType</type>
|
||||
</add-channel>
|
||||
|
||||
<!-- Commands -->
|
||||
<add-channel id="start_in_work_area" groupIds="command">
|
||||
<type>automower:startInWorkArea</type>
|
||||
</add-channel>
|
||||
</instruction-set>
|
||||
</thing-type>
|
||||
</update:update-descriptions>
|
||||
|
||||
Reference in New Issue
Block a user