mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-16 11:28:40 +00:00
Initial Solution
This commit is contained in:
@ -2,12 +2,8 @@
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/$defs/items"
|
||||
},
|
||||
"title": { "type": "string" },
|
||||
"items": { "$ref": "#/$defs/items" },
|
||||
"required": ["title", "items"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
@ -15,17 +11,19 @@
|
||||
"toggle": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"entity": { "$ref": "#/$defs/entity" },
|
||||
"name": { "title": "Your familiar name", "type": "string" },
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "toggle"
|
||||
},
|
||||
"tap_action": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirm": { "$ref": "#/$defs/confirm" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["entity", "name", "type"],
|
||||
@ -34,39 +32,24 @@
|
||||
"template": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"title": "What to display (template)",
|
||||
"type": "string"
|
||||
},
|
||||
"entity": { "$ref": "#/$defs/entity" },
|
||||
"name": { "title": "Your familiar name", "type": "string" },
|
||||
"content": { "title": "What to display (template)", "type": "string" },
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "template"
|
||||
},
|
||||
"tap_action": {
|
||||
"$ref": "#/$defs/action"
|
||||
}
|
||||
"tap_action": { "$ref": "#/$defs/tap_action" }
|
||||
},
|
||||
"required": ["name", "entity", "content", "type"],
|
||||
"required": ["name", "content", "type"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"tap": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"entity": { "$ref": "#/$defs/entity" },
|
||||
"name": { "title": "Your familiar name", "type": "string" },
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
@ -78,61 +61,43 @@
|
||||
"title": "Schema change:",
|
||||
"description": "Use 'tap_action' instead to mirror Home Assistant."
|
||||
},
|
||||
"tap_action": {
|
||||
"$ref": "#/$defs/action"
|
||||
}
|
||||
"tap_action": { "$ref": "#/$defs/tap_action" }
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"required": ["entity", "name", "type", "service"]
|
||||
},
|
||||
{
|
||||
"required": ["entity", "name", "type", "tap_action"]
|
||||
}
|
||||
{ "required": ["name", "type", "service"] },
|
||||
{ "required": ["name", "type", "tap_action"] }
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"menu": {
|
||||
"group": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
"$ref": "#/$defs/entity",
|
||||
"deprecated": true,
|
||||
"title": "Schema change:",
|
||||
"description": "'entity' is no longer necessary and should be removed."
|
||||
},
|
||||
"name": { "title": "Your familiar name", "type": "string" },
|
||||
"title": { "type": "string" },
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "group"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/$defs/items"
|
||||
}
|
||||
"items": { "$ref": "#/$defs/items" }
|
||||
},
|
||||
"required": ["entity", "name", "title", "type", "items"],
|
||||
"required": ["name", "title", "type", "items"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/toggle"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/template"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/tap"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/menu"
|
||||
}
|
||||
{ "$ref": "#/$defs/toggle" },
|
||||
{ "$ref": "#/$defs/template" },
|
||||
{ "$ref": "#/$defs/tap" },
|
||||
{ "$ref": "#/$defs/group" }
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -141,21 +106,24 @@
|
||||
"type": "string",
|
||||
"pattern": "^[^.]+\\.[^.]+$"
|
||||
},
|
||||
"action": {
|
||||
"tap_action": {
|
||||
"title": "Action",
|
||||
"description": "'confirm' field is optional.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": {
|
||||
"$ref": "#/$defs/entity"
|
||||
"service": { "$ref": "#/$defs/entity" },
|
||||
"confirm": { "$ref": "#/$defs/confirm" },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "The object containing the parameters and their values to be passed to the entity. No schema checking can be done here, you are on your own! On application crash, remove the parameters."
|
||||
}
|
||||
},
|
||||
"required": ["service"]
|
||||
},
|
||||
"confirm": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Confirm the action before execution as a precaution."
|
||||
}
|
||||
},
|
||||
"required": ["service"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,14 +28,13 @@ using Toybox.WatchUi;
|
||||
using Toybox.Timer;
|
||||
|
||||
class Alert extends WatchUi.View {
|
||||
private static const bRadius = 10;
|
||||
private static const scRadius = 10;
|
||||
private var mTimer as Timer.Timer;
|
||||
private var mTimeout as Lang.Number;
|
||||
private var mText as Lang.String;
|
||||
private var mFont as Graphics.FontType;
|
||||
private var mFgcolor as Graphics.ColorType;
|
||||
private var mBgcolor as Graphics.ColorType;
|
||||
private var mAntiAlias as Lang.Boolean = false;
|
||||
|
||||
function initialize(params as Lang.Dictionary) {
|
||||
View.initialize();
|
||||
@ -65,10 +64,6 @@ class Alert extends WatchUi.View {
|
||||
mTimeout = 2000;
|
||||
}
|
||||
|
||||
if (Graphics.Dc has :setAntiAlias) {
|
||||
mAntiAlias = true;
|
||||
}
|
||||
|
||||
mTimer = new Timer.Timer();
|
||||
}
|
||||
|
||||
@ -88,7 +83,7 @@ class Alert extends WatchUi.View {
|
||||
var bX = (dc.getWidth() - bWidth) / 2;
|
||||
var bY = (dc.getHeight() - bHeight) / 2;
|
||||
|
||||
if (mAntiAlias) {
|
||||
if (Graphics.Dc has :setAntiAlias) {
|
||||
dc.setAntiAlias(true);
|
||||
}
|
||||
|
||||
@ -98,7 +93,7 @@ class Alert extends WatchUi.View {
|
||||
);
|
||||
dc.clear();
|
||||
dc.setColor(mBgcolor, mBgcolor);
|
||||
dc.fillRoundedRectangle(bX, bY, bWidth, bHeight, bRadius);
|
||||
dc.fillRoundedRectangle(bX, bY, bWidth, bHeight, scRadius);
|
||||
|
||||
dc.setColor(mFgcolor, mBgcolor);
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
@ -106,7 +101,7 @@ class Alert extends WatchUi.View {
|
||||
bY += i;
|
||||
bWidth -= (2 * i);
|
||||
bHeight -= (2 * i);
|
||||
dc.drawRoundedRectangle(bX, bY, bWidth, bHeight, bRadius);
|
||||
dc.drawRoundedRectangle(bX, bY, bWidth, bHeight, scRadius);
|
||||
}
|
||||
|
||||
var tX = dc.getWidth() / 2;
|
||||
|
@ -36,11 +36,9 @@ using Toybox.Communications;
|
||||
using Toybox.Timer;
|
||||
|
||||
class ErrorView extends ScalableView {
|
||||
private static const scErrorIconMargin as Lang.Float = 7f;
|
||||
private var mText as Lang.String = "";
|
||||
private var mDelegate as ErrorDelegate;
|
||||
private const cSettings as Lang.Dictionary = {
|
||||
:errorIconMargin => 7f
|
||||
};
|
||||
// Vertical spacing between the top of the face and the error icon
|
||||
private var mErrorIconMargin as Lang.Number;
|
||||
private var mErrorIcon;
|
||||
@ -54,7 +52,7 @@ class ErrorView extends ScalableView {
|
||||
ScalableView.initialize();
|
||||
mDelegate = new ErrorDelegate(self);
|
||||
// Convert the settings from % of screen size to pixels
|
||||
mErrorIconMargin = pixelsForScreen(cSettings.get(:errorIconMargin) as Lang.Float);
|
||||
mErrorIconMargin = pixelsForScreen(scErrorIconMargin);
|
||||
mErrorIcon = Application.loadResource(Rez.Drawables.ErrorIcon) as Graphics.BitmapResource;
|
||||
if (Graphics.Dc has :setAntiAlias) {
|
||||
mAntiAlias = true;
|
||||
|
@ -34,12 +34,14 @@ class HomeAssistantConfirmation extends WatchUi.Confirmation {
|
||||
}
|
||||
|
||||
class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
|
||||
private var mConfirmMethod;
|
||||
private var mTimer;
|
||||
private var mConfirmMethod as Method(state as Lang.Boolean) as Void;
|
||||
private var mTimer as Timer.Timer or Null;
|
||||
private var mState as Lang.Boolean;
|
||||
|
||||
function initialize(callback as Method() as Void) {
|
||||
function initialize(callback as Method(state as Lang.Boolean) as Void, state as Lang.Boolean) {
|
||||
WatchUi.ConfirmationDelegate.initialize();
|
||||
mConfirmMethod = callback;
|
||||
mState = state;
|
||||
var timeout = Settings.getConfirmTimeout(); // ms
|
||||
if (timeout > 0) {
|
||||
mTimer = new Timer.Timer();
|
||||
@ -49,11 +51,11 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
|
||||
|
||||
function onResponse(response) as Lang.Boolean {
|
||||
getApp().getQuitTimer().reset();
|
||||
if (mTimer) {
|
||||
if (mTimer != null) {
|
||||
mTimer.stop();
|
||||
}
|
||||
if (response == WatchUi.CONFIRM_YES) {
|
||||
mConfirmMethod.invoke();
|
||||
mConfirmMethod.invoke(mState);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -64,9 +64,14 @@ class HomeAssistantMenuItemFactory {
|
||||
return instance;
|
||||
}
|
||||
|
||||
function toggle(label as Lang.String or Lang.Symbol, entity_id as Lang.String or Null) as WatchUi.MenuItem {
|
||||
function toggle(
|
||||
label as Lang.String or Lang.Symbol,
|
||||
entity_id as Lang.String or Null,
|
||||
confirm as Lang.Boolean
|
||||
) as WatchUi.MenuItem {
|
||||
return new HomeAssistantToggleMenuItem(
|
||||
label,
|
||||
confirm,
|
||||
{ "entity_id" => entity_id },
|
||||
mMenuItemOptions
|
||||
);
|
||||
|
@ -57,15 +57,16 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem {
|
||||
if (mConfirm) {
|
||||
WatchUi.pushView(
|
||||
new HomeAssistantConfirmation(),
|
||||
new HomeAssistantConfirmationDelegate(method(:onConfirm)),
|
||||
new HomeAssistantConfirmationDelegate(method(:onConfirm), false),
|
||||
WatchUi.SLIDE_IMMEDIATE
|
||||
);
|
||||
} else {
|
||||
onConfirm();
|
||||
mHomeAssistantService.call(mService, mData);
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm() as Void {
|
||||
// NB. Parameter 'b' is ignored
|
||||
function onConfirm(b as Lang.Boolean) as Void {
|
||||
mHomeAssistantService.call(mService, mData);
|
||||
}
|
||||
|
||||
|
@ -64,15 +64,16 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem {
|
||||
if (mConfirm) {
|
||||
WatchUi.pushView(
|
||||
new HomeAssistantConfirmation(),
|
||||
new HomeAssistantConfirmationDelegate(method(:onConfirm)),
|
||||
new HomeAssistantConfirmationDelegate(method(:onConfirm), false),
|
||||
WatchUi.SLIDE_IMMEDIATE
|
||||
);
|
||||
} else {
|
||||
onConfirm();
|
||||
onConfirm(false);
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm() as Void {
|
||||
// NB. Parameter 'b' is ignored
|
||||
function onConfirm(b as Lang.Boolean) as Void {
|
||||
if (mService != null) {
|
||||
mHomeAssistantService.call(mService, mData);
|
||||
}
|
||||
@ -181,9 +182,7 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem {
|
||||
}
|
||||
Communications.makeWebRequest(
|
||||
url,
|
||||
{
|
||||
"template" => mTemplate
|
||||
},
|
||||
{ "template" => mTemplate },
|
||||
{
|
||||
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
||||
:headers => {
|
||||
|
@ -25,10 +25,12 @@ using Toybox.Application.Properties;
|
||||
using Toybox.Timer;
|
||||
|
||||
class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
private var mConfirm as Lang.Boolean;
|
||||
private var mData as Lang.Dictionary;
|
||||
|
||||
function initialize(
|
||||
label as Lang.String or Lang.Symbol,
|
||||
confirm as Lang.Boolean,
|
||||
data as Lang.Dictionary or Null,
|
||||
options as {
|
||||
:alignment as WatchUi.MenuItem.Alignment,
|
||||
@ -36,6 +38,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
} or Null
|
||||
) {
|
||||
WatchUi.ToggleMenuItem.initialize(label, null, null, false, options);
|
||||
mConfirm = confirm;
|
||||
mData = data;
|
||||
}
|
||||
|
||||
@ -301,4 +304,20 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
}
|
||||
}
|
||||
|
||||
function callService(b as Lang.Boolean) as Void {
|
||||
if (mConfirm) {
|
||||
WatchUi.pushView(
|
||||
new HomeAssistantConfirmation(),
|
||||
new HomeAssistantConfirmationDelegate(method(:onConfirm), b),
|
||||
WatchUi.SLIDE_IMMEDIATE
|
||||
);
|
||||
} else {
|
||||
setState(b);
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm(b as Lang.Boolean) as Void {
|
||||
setState(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class HomeAssistantView extends WatchUi.Menu2 {
|
||||
}
|
||||
if (type != null && name != null) {
|
||||
if (type.equals("toggle") && entity != null) {
|
||||
addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity));
|
||||
addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity, confirm));
|
||||
} else if (type.equals("template") && content != null) {
|
||||
if (service == null) {
|
||||
addItem(HomeAssistantMenuItemFactory.create().template_notap(name, content));
|
||||
@ -149,7 +149,7 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate {
|
||||
if (Globals.scDebug) {
|
||||
System.println(haToggleItem.getLabel() + " " + haToggleItem.getId() + " " + haToggleItem.isEnabled());
|
||||
}
|
||||
haToggleItem.setState(haToggleItem.isEnabled());
|
||||
haToggleItem.callService(haToggleItem.isEnabled());
|
||||
} else if (item instanceof HomeAssistantTapMenuItem) {
|
||||
var haItem = item as HomeAssistantTapMenuItem;
|
||||
if (Globals.scDebug) {
|
||||
|
@ -27,6 +27,7 @@ using Toybox.System;
|
||||
|
||||
// Can use push view so must never be run in a glance context
|
||||
class WebhookManager {
|
||||
|
||||
function onReturnRequestWebhookId(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
|
||||
switch (responseCode) {
|
||||
case Communications.BLE_HOST_TIMEOUT:
|
||||
@ -243,4 +244,5 @@ class WebhookManager {
|
||||
method(:onReturnRegisterWebhookSensor)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user