Fix for the update rate

Now perform a "round robin" of all toggle menu items. The delay is currently 100 ms to avoid Communications.BLE_QUEUE_FULL errors.
This commit is contained in:
Philip Abbey
2023-11-11 13:36:08 +00:00
parent b7ed8607fb
commit e7c4411dd2
40 changed files with 128 additions and 55 deletions

View File

@ -23,8 +23,9 @@ using Toybox.Lang;
class Globals {
// Enable printing of messages to the debug console (don't make this a Property
// as the messages can't be read from a watch!)
static const debug = false;
static const updateInterval = 10; // seconds
static const alertTimeout = 2000; // ms
static const tapTimeout = 1000; // ms
static const debug = false;
// There's a danger this time is device sensitive.
static const menuItemUpdateInterval = 100; // ms, 100 ms seems okay for Venu2
static const alertTimeout = 2000; // ms
static const tapTimeout = 1000; // ms
}

View File

@ -31,7 +31,10 @@ class HomeAssistantApp extends Application.AppBase {
hidden var strNoConfigUrl as Lang.String;
hidden var strNoInternet as Lang.String;
hidden var strNoMenu as Lang.String;
hidden var strApiFlood as Lang.String;
hidden var timer as Timer.Timer;
hidden var itemsToUpdate; // Array initialised by onReturnFetchMenuConfig()
hidden var nextItemToUpdate = 0; // Index into the above array
function initialize() {
AppBase.initialize();
@ -40,6 +43,7 @@ class HomeAssistantApp extends Application.AppBase {
strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
strNoMenu = WatchUi.loadResource($.Rez.Strings.NoMenu);
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
timer = new Timer.Timer();
}
@ -89,14 +93,24 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: " + responseCode);
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Data: " + data);
}
if (responseCode == 200) {
if (responseCode == Communications.BLE_QUEUE_FULL) {
if (Globals.debug) {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
var cw = WatchUi.getCurrentView();
if (!(cw[0] instanceof ErrorView)) {
// Avoid pushing multiple ErrorViews
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
}
} else if (responseCode == 200) {
haMenu = new HomeAssistantView(data, null);
WatchUi.switchToView(haMenu, new HomeAssistantViewDelegate(), WatchUi.SLIDE_IMMEDIATE);
itemsToUpdate = haMenu.getItemsToUpdate();
timer.start(
haMenu.method(:stateUpdate),
Globals.updateInterval * 1000,
method(:updateNextMenuItem),
Globals.menuItemUpdateInterval,
true
);
WatchUi.switchToView(haMenu, new HomeAssistantViewDelegate(), WatchUi.SLIDE_IMMEDIATE);
} else if (responseCode == -300) {
if (Globals.debug) {
System.println("HomeAssistantApp Note - onReturnFetchMenuConfig(): Network request timeout.");
@ -123,6 +137,14 @@ class HomeAssistantApp extends Application.AppBase {
);
}
// We need to spread out the API calls so as not to overload the results queue and cause Communications.BLE_QUEUE_FULL (-101) error.
// This function is called by a timer every Globals.menuItemUpdateInterval ms.
function updateNextMenuItem() as Void {
var itu = itemsToUpdate as Lang.Array<HomeAssistantToggleMenuItem>;
itu[nextItemToUpdate].getState();
nextItemToUpdate = (nextItemToUpdate + 1) % itu.size();
}
}
function getApp() as HomeAssistantApp {

View File

@ -26,6 +26,7 @@ using Toybox.Application.Properties;
class HomeAssistantMenuItem extends WatchUi.MenuItem {
hidden var api_key = Properties.getValue("api_key");
hidden var strNoInternet as Lang.String;
hidden var strApiFlood as Lang.String;
hidden var mService as Lang.String or Null;
function initialize(
@ -39,6 +40,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
} or Null
) {
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
mService = service;
WatchUi.MenuItem.initialize(
label,
@ -52,10 +54,19 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
//
function onReturnExecScript(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
if (Globals.debug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: " + responseCode);
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
System.println("HomeAssistantMenuItem onReturnExecScript() Response Code: " + responseCode);
System.println("HomeAssistantMenuItem onReturnExecScript() Response Data: " + data);
}
if (responseCode == 200) {
if (responseCode == Communications.BLE_QUEUE_FULL) {
if (Globals.debug) {
System.println("HomeAssistantMenuItem onReturnExecScript() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
var cw = WatchUi.getCurrentView();
if (!(cw[0] instanceof ErrorView)) {
// Avoid pushing multiple ErrorViews
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
}
} else if (responseCode == 200) {
var d = data as Lang.Array;
for(var i = 0; i < d.size(); i++) {
if ((d[i].get("entity_id") as Lang.String).equals(mIdentifier)) {

View File

@ -26,6 +26,7 @@ using Toybox.Application.Properties;
class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
hidden var api_key = Properties.getValue("api_key");
hidden var strNoInternet as Lang.String;
hidden var strApiFlood as Lang.String;
function initialize(
label as Lang.String or Lang.Symbol,
@ -41,6 +42,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
} or Null
) {
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
WatchUi.ToggleMenuItem.initialize(label, subLabel, identifier, enabled, options);
api_key = Properties.getValue("api_key");
}
@ -64,7 +66,16 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: " + responseCode);
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
}
if (responseCode == 200) {
if (responseCode == Communications.BLE_QUEUE_FULL) {
if (Globals.debug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
var cw = WatchUi.getCurrentView();
if (!(cw[0] instanceof ErrorView)) {
// Avoid pushing multiple ErrorViews
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
}
} else if (responseCode == 200) {
var state = data.get("state") as Lang.String;
if (Globals.debug) {
System.println((data.get("attributes") as Lang.Dictionary).get("friendly_name") + " State=" + state);
@ -107,10 +118,19 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
//
function onReturnSetState(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
if (Globals.debug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: " + responseCode);
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: " + responseCode);
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Data: " + data);
}
if (responseCode == 200) {
if (responseCode == Communications.BLE_QUEUE_FULL) {
if (Globals.debug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
var cw = WatchUi.getCurrentView();
if (!(cw[0] instanceof ErrorView)) {
// Avoid pushing multiple ErrorViews
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
}
} else if (responseCode == 200) {
var state;
var d = data as Lang.Array;
for(var i = 0; i < d.size(); i++) {

View File

@ -24,6 +24,9 @@ using Toybox.WatchUi;
class HomeAssistantView extends WatchUi.Menu2 {
hidden var strMenuItemTap as Lang.String;
// List of items that need to have their status updated periodically
hidden var mListToggleItems = [];
hidden var mListMenuItems = [];
function initialize(
definition as Lang.Dictionary,
@ -56,15 +59,15 @@ class HomeAssistantView extends WatchUi.Menu2 {
var service = items[i].get("service") as Lang.String or Null;
if (type != null && name != null && entity != null) {
if (type.equals("toggle")) {
addItem(
new HomeAssistantToggleMenuItem(
name,
toggle_obj,
entity,
false,
null
)
var item = new HomeAssistantToggleMenuItem(
name,
toggle_obj,
entity,
false,
null
);
addItem(item);
mListToggleItems.add(item);
} else if (type.equals("tap")) {
addItem(
new HomeAssistantMenuItem(
@ -76,46 +79,27 @@ class HomeAssistantView extends WatchUi.Menu2 {
)
);
} else if (type.equals("group")) {
addItem(
new HomeAssistantViewMenuItem(items[i])
);
var item = new HomeAssistantViewMenuItem(items[i]);
addItem(item);
mListMenuItems.add(item);
}
}
}
}
function getItemsToUpdate() as Lang.Array<HomeAssistantToggleMenuItem> {
var fullList = [];
var lmi = mListMenuItems as Lang.Array<HomeAssistantViewMenuItem>;
for(var i = 0; i < lmi.size(); i++) {
fullList.addAll(lmi[i].getMenuView().getItemsToUpdate());
}
return fullList.addAll(mListToggleItems);
}
// Called when this View is brought to the foreground. Restore
// the state of this View and prepare it to be shown. This includes
// loading resources into memory.
function onShow() as Void {
for(var i = 0; i < mItems.size(); i++) {
if (mItems[i] instanceof HomeAssistantToggleMenuItem) {
var toggleItem = mItems[i] as HomeAssistantToggleMenuItem;
toggleItem.getState();
if (Globals.debug) {
System.println("HomeAssistantView Note: " + toggleItem.getLabel() + " ID=" + toggleItem.getId() + " Enabled=" + toggleItem.isEnabled());
}
}
}
}
function stateUpdate() as Void {
for(var i = 0; i < mItems.size(); i++) {
if (mItems[i] instanceof HomeAssistantToggleMenuItem) {
var toggleItem = mItems[i] as HomeAssistantToggleMenuItem;
toggleItem.getState();
if (Globals.debug) {
System.println("HomeAssistantView Toggle stateUpdate: " + toggleItem.getLabel() + " ID=" + toggleItem.getId() + " Enabled=" + toggleItem.isEnabled());
}
} else if (mItems[i] instanceof HomeAssistantViewMenuItem) {
var menu = mItems[i] as HomeAssistantViewMenuItem;
if (Globals.debug) {
System.println("HomeAssistantView Menu stateUpdate: " + menu.getLabel() + " ID=" + menu.getId());
}
menu.getMenuView().stateUpdate();
}
}
}
function onShow() as Void {}
}