Comments & Dictionaries

Reformatted comments to work in VSCode and converted `dict.get(:key)` to `dict[:key]` syntax as its nicer.
This commit is contained in:
Philip Abbey
2025-07-24 18:54:27 +01:00
parent 70f05e8912
commit 8868f2152c
18 changed files with 207 additions and 184 deletions

View File

@ -35,38 +35,38 @@ class Alert extends WatchUi.View {
//! Class Constructor //! Class Constructor
//! @param params A dictionary object as follows:<br> //! @param params A dictionary object as follows:<br>
//! &lbrace;<br> //! `{`<br>
//! &emsp; :timeout as Lang.Number, // Timeout in millseconds<br> //! &emsp; `:timeout as Lang.Number,` // Timeout in millseconds<br>
//! &emsp; :font as Graphics.FontType, // Text font size<br> //! &emsp; `:font as Graphics.FontType,` // Text font size<br>
//! &emsp; :text as Lang.String, // Text to display<br> //! &emsp; `:text as Lang.String,` // Text to display<br>
//! &emsp; :fgcolor as Graphics.ColorType, // Foreground Colour<br> //! &emsp; `:fgcolor as Graphics.ColorType,` // Foreground Colour<br>
//! &emsp; :bgcolor as Graphics.ColorType // Background Colour<br> //! &emsp; `:bgcolor as Graphics.ColorType` // Background Colour<br>
//! &rbrace; //! `}`
// //
function initialize(params as Lang.Dictionary) { function initialize(params as Lang.Dictionary) {
View.initialize(); View.initialize();
mText = params.get(:text) as Lang.String; mText = params[:text] as Lang.String;
if (mText == null) { if (mText == null) {
mText = "Alert"; mText = "Alert";
} }
mFont = params.get(:font) as Graphics.FontType; mFont = params[:font] as Graphics.FontType;
if (mFont == null) { if (mFont == null) {
mFont = Graphics.FONT_MEDIUM; mFont = Graphics.FONT_MEDIUM;
} }
mFgcolor = params.get(:fgcolor) as Graphics.ColorType; mFgcolor = params[:fgcolor] as Graphics.ColorType;
if (mFgcolor == null) { if (mFgcolor == null) {
mFgcolor = Graphics.COLOR_BLACK; mFgcolor = Graphics.COLOR_BLACK;
} }
mBgcolor = params.get(:bgcolor) as Graphics.ColorType; mBgcolor = params[:bgcolor] as Graphics.ColorType;
if (mBgcolor == null) { if (mBgcolor == null) {
mBgcolor = Graphics.COLOR_WHITE; mBgcolor = Graphics.COLOR_WHITE;
} }
mTimeout = params.get(:timeout) as Lang.Number; mTimeout = params[:timeout] as Lang.Number;
if (mTimeout == null) { if (mTimeout == null) {
mTimeout = 2000; mTimeout = 2000;
} }

View File

@ -45,10 +45,10 @@ class BackgroundServiceDelegate extends System.ServiceDelegate {
//! Called on completion of an activity. //! Called on completion of an activity.
//! //!
//! @param activity Specified as a Dictionary with two items.<br> //! @param activity Specified as a Dictionary with two items.<br>
//! &lbrace;<br> //! `{`<br>
//! &emsp; :sport as Activity.Sport<br> //! &emsp; `:sport as Activity.Sport`<br>
//! &emsp; :subSport as Activity.SubSport<br> //! &emsp; `:subSport as Activity.SubSport`<br>
//! &rbrace; //! `}`
// //
function onActivityCompleted( function onActivityCompleted(
activity as { activity as {
@ -101,8 +101,8 @@ class BackgroundServiceDelegate extends System.ServiceDelegate {
//! @param sub_activity Activity.SubSport //! @param sub_activity Activity.SubSport
// //
private function doUpdate( private function doUpdate(
activity as Lang.Number or Null, activity as Lang.Number?,
sub_activity as Lang.Number or Null sub_activity as Lang.Number?
) { ) {
// System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call."); // System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call.");
var position = Position.getInfo(); var position = Position.getInfo();

View File

@ -39,7 +39,7 @@ class ErrorView extends ScalableView {
// Vertical spacing between the top of the face and the error icon // Vertical spacing between the top of the face and the error icon
private var mErrorIconMargin as Lang.Number; private var mErrorIconMargin as Lang.Number;
private var mErrorIcon; private var mErrorIcon;
private var mTextArea as WatchUi.TextArea or Null; private var mTextArea as WatchUi.TextArea?;
private var mAntiAlias as Lang.Boolean = false; private var mAntiAlias as Lang.Boolean = false;
private static var instance; private static var instance;
@ -169,7 +169,7 @@ class ErrorDelegate extends WatchUi.BehaviorDelegate {
WatchUi.BehaviorDelegate.initialize(); WatchUi.BehaviorDelegate.initialize();
} }
//! Process the event to clear the ErrorView. //! Handle the back button (ESC) to clear the ErrorView.
// //
function onBack() as Lang.Boolean { function onBack() as Lang.Boolean {
getApp().getQuitTimer().reset(); getApp().getQuitTimer().reset();

View File

@ -25,22 +25,22 @@ using Toybox.Timer;
// //
(:glance, :background) (:glance, :background)
class HomeAssistantApp extends Application.AppBase { class HomeAssistantApp extends Application.AppBase {
private var mApiStatus as Lang.String or Null; private var mApiStatus as Lang.String?;
private var mHasToast as Lang.Boolean = false; private var mHasToast as Lang.Boolean = false;
private var mMenuStatus as Lang.String or Null; private var mMenuStatus as Lang.String?;
private var mHaMenu as HomeAssistantView or Null; private var mHaMenu as HomeAssistantView?;
private var mGlanceTemplate as Lang.String or Null = null; private var mGlanceTemplate as Lang.String? = null;
private var mGlanceText as Lang.String or Null = null; private var mGlanceText as Lang.String? = null;
private var mQuitTimer as QuitTimer or Null; private var mQuitTimer as QuitTimer?;
private var mGlanceTimer as Timer.Timer or Null; private var mGlanceTimer as Timer.Timer?;
private var mUpdateTimer as Timer.Timer or Null; private var mUpdateTimer as Timer.Timer?;
// Array initialised by onReturnFetchMenuConfig() // Array initialised by onReturnFetchMenuConfig()
private var mItemsToUpdate as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem> or Null; private var mItemsToUpdate as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem>?;
private var mIsGlance as Lang.Boolean = false; private var mIsGlance as Lang.Boolean = false;
private var mIsApp as Lang.Boolean = false; // Or Widget private var mIsApp as Lang.Boolean = false; // Or Widget
private var mUpdating as Lang.Boolean = false; // Don't start a second chain of updates private var mUpdating as Lang.Boolean = false; // Don't start a second chain of updates
private var mTemplates as Lang.Dictionary = {}; private var mTemplates as Lang.Dictionary = {};
private var mNotifiedNoBle as Lang.Boolean = false; private var mNotifiedNoBle as Lang.Boolean = false;
private const wifiPollDelayMs = 2000; private const wifiPollDelayMs = 2000;
@ -239,15 +239,13 @@ class HomeAssistantApp extends Application.AppBase {
//! Can we use the cached menu? //! Can we use the cached menu?
//! //!
//! @return Return true if there's a menu in cache, and if the user has enabled the cache and //! @return Return true if there's a menu in cache, and if the user has enabled the cache and
//! has not requested to have the cache busted. //! has not requested to have the cache refreshed.
// //
function hasCachedMenu() as Lang.Boolean { function hasCachedMenu() as Lang.Boolean {
if (Settings.getClearCache() || !Settings.getCacheConfig()) { if (Settings.getClearCache() || !Settings.getCacheConfig()) {
return false; return false;
} }
return (Storage.getValue("menu") as Lang.Dictionary) != null;
var menu = Storage.getValue("menu") as Lang.Dictionary;
return menu != null;
} }
//! Fetch the menu configuration over HTTPS, which might be locally cached. //! Fetch the menu configuration over HTTPS, which might be locally cached.
@ -757,10 +755,10 @@ class HomeAssistantApp extends Application.AppBase {
//! Return the optional glance text that overrides the default glance content. This //! Return the optional glance text that overrides the default glance content. This
//! is derived from the glance template. //! is derived from the glance template.
//! //!
//! @return A string derived from the glance template //! @return A string derived from the glance template (or null)
// //
(:glance) (:glance)
function getGlanceText() as Lang.String or Null { function getGlanceText() as Lang.String? {
return mGlanceText; return mGlanceText;
} }

View File

@ -35,27 +35,30 @@ class HomeAssistantConfirmation extends WatchUi.Confirmation {
//! Delegate to respond to the confirmation request. //! Delegate to respond to the confirmation request.
// //
class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate { class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
private static var mTimer as Timer.Timer or Null; private static var mTimer as Timer.Timer?;
private var mConfirmMethod as Method(state as Lang.Boolean) as Void;
private var mConfirmMethod as Method(state as Lang.Boolean) as Void; private var mState as Lang.Boolean;
private var mState as Lang.Boolean; private var mToggleMethod as Method(state as Lang.Boolean) as Void or Null;
private var mToggleMethod as Method(state as Lang.Boolean) as Void or Null; private var mConfirmationView as WatchUi.Confirmation;
private var mConfirmationView as WatchUi.Confirmation;
//! Class Constructor //! Class Constructor
//! //!
//! @param options A dictionary describing the following options: //! @param options A dictionary describing the following options:<br>
//! - callback Method to call on confirmation. //! `{`<br>
//! - confirmationView Confirmation the delegate is active for //! &emsp; `:callback as Method(state as Lang.Boolean) as Void,` // Method to call on confirmation.<br>
//! - state Wanted state of a toggle button. //! &emsp; `:confirmationView as WatchUi.Confirmation,` // Confirmation the delegate is active for<br>
//! - toggle Optional setEnabled method to untoggle ToggleItem. //! &emsp; `:state as Lang.Boolean,` // Wanted state of a toggle button.<br>
//! &emsp; `:toggle as Method(state as Lang.Boolean)?` // Optional setEnabled method to untoggle ToggleItem.<br>
//! `}`
// //
function initialize(options as { function initialize(
:callback as Method(state as Lang.Boolean) as Void, options as {
:confirmationView as WatchUi.Confirmation, :callback as Method(state as Lang.Boolean) as Void,
:state as Lang.Boolean, :confirmationView as WatchUi.Confirmation,
:toggleMethod as Method(state as Lang.Boolean) or Null, :state as Lang.Boolean,
}) { :toggleMethod as Method(state as Lang.Boolean)?
}
) {
if (mTimer != null) { if (mTimer != null) {
mTimer.stop(); mTimer.stop();
} }
@ -78,7 +81,7 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
//! Respond to the confirmation event. //! Respond to the confirmation event.
//! //!
//! @param response code //! @param response response code
//! @return Required to meet the function prototype, but the base class does not indicate a definition. //! @return Required to meet the function prototype, but the base class does not indicate a definition.
// //
function onResponse(response as WatchUi.Confirm) as Lang.Boolean { function onResponse(response as WatchUi.Confirm) as Lang.Boolean {
@ -98,6 +101,7 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
} }
//! Function supplied to a timer in order to limit the time for which the confirmation can be provided. //! Function supplied to a timer in order to limit the time for which the confirmation can be provided.
//
function onTimeout() as Void { function onTimeout() as Void {
mTimer.stop(); mTimer.stop();
// Undo the toggle, if we have one // Undo the toggle, if we have one

View File

@ -44,12 +44,12 @@ class HomeAssistantGlanceView extends WatchUi.GlanceView {
private var mTextWidth as Lang.Number = 0; private var mTextWidth as Lang.Number = 0;
// Re-usable text items for drawing // Re-usable text items for drawing
private var mApp as HomeAssistantApp; private var mApp as HomeAssistantApp;
private var mTitle as WatchUi.Text or Null; private var mTitle as WatchUi.Text?;
private var mApiText as WatchUi.Text or Null; private var mApiText as WatchUi.Text?;
private var mApiStatus as WatchUi.Text or Null; private var mApiStatus as WatchUi.Text?;
private var mMenuText as WatchUi.Text or Null; private var mMenuText as WatchUi.Text?;
private var mMenuStatus as WatchUi.Text or Null; private var mMenuStatus as WatchUi.Text?;
private var mGlanceContent as WatchUi.TextArea or Null; private var mGlanceContent as WatchUi.TextArea?;
private var mAntiAlias as Lang.Boolean = false; private var mAntiAlias as Lang.Boolean = false;
//! Class Constructor //! Class Constructor

View File

@ -30,7 +30,7 @@ class HomeAssistantGroupMenuItem extends HomeAssistantMenuItem {
icon as WatchUi.Drawable, icon as WatchUi.Drawable,
options as { options as {
:alignment as WatchUi.MenuItem.Alignment :alignment as WatchUi.MenuItem.Alignment
} or Null }?
) { ) {
if (options != null) { if (options != null) {
options.put(:icon, icon); options.put(:icon, icon);

View File

@ -20,7 +20,7 @@ using Toybox.Graphics;
//! Generic menu button with an icon that optionally renders a Home Assistant Template. //! Generic menu button with an icon that optionally renders a Home Assistant Template.
// //
class HomeAssistantMenuItem extends WatchUi.IconMenuItem { class HomeAssistantMenuItem extends WatchUi.IconMenuItem {
private var mTemplate as Lang.String or Null; private var mTemplate as Lang.String?;
//! Class Constructor //! Class Constructor
//! //!
@ -34,13 +34,13 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem {
options as { options as {
:alignment as WatchUi.MenuItem.Alignment, :alignment as WatchUi.MenuItem.Alignment,
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
} or Null }?
) { ) {
WatchUi.IconMenuItem.initialize( WatchUi.IconMenuItem.initialize(
label, label,
null, null,
null, null,
options.get(:icon), options[:icon],
options options
); );
mTemplate = template; mTemplate = template;
@ -56,9 +56,9 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem {
//! Return the menu item's template. //! Return the menu item's template.
//! //!
//! @return A string with the menu item's template definition. //! @return A string with the menu item's template definition (or null).
// //
function getTemplate() as Lang.String or Null { function getTemplate() as Lang.String? {
return mTemplate; return mTemplate;
} }

View File

@ -74,8 +74,8 @@ class HomeAssistantMenuItemFactory {
// //
function toggle( function toggle(
label as Lang.String or Lang.Symbol, label as Lang.String or Lang.Symbol,
entity_id as Lang.String or Null, entity_id as Lang.String?,
template as Lang.String or Null, template as Lang.String?,
options as { options as {
:exit as Lang.Boolean, :exit as Lang.Boolean,
:confirm as Lang.Boolean, :confirm as Lang.Boolean,
@ -104,11 +104,11 @@ class HomeAssistantMenuItemFactory {
//! @param options Menu item options to be passed on, including both SDK and menu options, e.g. exit, confirm & pin. //! @param options Menu item options to be passed on, including both SDK and menu options, e.g. exit, confirm & pin.
// //
function tap( function tap(
label as Lang.String or Lang.Symbol, label as Lang.String or Lang.Symbol,
entity_id as Lang.String or Null, entity_id as Lang.String?,
template as Lang.String or Null, template as Lang.String?,
service as Lang.String or Null, service as Lang.String?,
data as Lang.Dictionary or Null, data as Lang.Dictionary?,
options as { options as {
:exit as Lang.Boolean, :exit as Lang.Boolean,
:confirm as Lang.Boolean, :confirm as Lang.Boolean,
@ -156,7 +156,7 @@ class HomeAssistantMenuItemFactory {
// //
function group( function group(
definition as Lang.Dictionary, definition as Lang.Dictionary,
template as Lang.String or Null template as Lang.String?
) as WatchUi.MenuItem { ) as WatchUi.MenuItem {
return new HomeAssistantGroupMenuItem( return new HomeAssistantGroupMenuItem(
definition, definition,

View File

@ -83,16 +83,16 @@ class PinDigit extends WatchUi.Selectable {
//! Class Constructor //! Class Constructor
//! //!
//! @param options See `Drawable.initialize()`, but with `:label` and `:touched` added.<br> //! @param options See `Drawable.initialize()`, but with `:label` and `:touched` added.<br>
//! &lbrace;<br> //! `{`<br>
//! &emsp; :label as Lang.Number, // The digit 0..9 to display<br> //! &emsp; `:label as Lang.Number,` // The digit 0..9 to display<br>
//! &emsp; :touched as Lang.Boolean, // Should the digit be filled to indicate it has been pressed?<br> //! &emsp; `:touched as Lang.Boolean,` // Should the digit be filled to indicate it has been pressed?<br>
//! &emsp; + those required by `Drawable.initialize()`<br> //! &emsp; + those required by `Drawable.initialize()`<br>
//! &rbrace; //! ``}`
// //
function initialize(options) { function initialize(options) {
Drawable.initialize(options); Drawable.initialize(options);
mText = options.get(:label); mText = options[:label];
mTouched = options.get(:touched); mTouched = options[:touched];
} }
//! Draw the PIN digit button. //! Draw the PIN digit button.
@ -182,10 +182,10 @@ class HomeAssistantPinConfirmationDelegate extends WatchUi.BehaviorDelegate {
private var mPin as Lang.String; private var mPin as Lang.String;
private var mEnteredPin as Lang.String; private var mEnteredPin as Lang.String;
private var mConfirmMethod as Method(state as Lang.Boolean) as Void; private var mConfirmMethod as Method(state as Lang.Boolean) as Void;
private var mTimer as Timer.Timer or Null; private var mTimer as Timer.Timer?;
private var mState as Lang.Boolean; private var mState as Lang.Boolean;
private var mFailures as PinFailures; private var mFailures as PinFailures;
private var mToggleMethod as Method(state as Lang.Boolean) as Void or Null; private var mToggleMethod as Method(state as Lang.Boolean) as Void?;
private var mView as HomeAssistantPinConfirmationView; private var mView as HomeAssistantPinConfirmationView;
//! Class Constructor //! Class Constructor
@ -202,7 +202,7 @@ class HomeAssistantPinConfirmationDelegate extends WatchUi.BehaviorDelegate {
:pin as Lang.String, :pin as Lang.String,
:state as Lang.Boolean, :state as Lang.Boolean,
:view as HomeAssistantPinConfirmationView, :view as HomeAssistantPinConfirmationView,
:toggleMethod as (Method(state as Lang.Boolean) as Void) or Null, :toggleMethod as (Method(state as Lang.Boolean) as Void)?,
}) { }) {
BehaviorDelegate.initialize(); BehaviorDelegate.initialize();
mFailures = new PinFailures(); mFailures = new PinFailures();
@ -334,7 +334,7 @@ class PinFailures {
const STORAGE_KEY_LOCKED as Lang.String = "pin_locked"; const STORAGE_KEY_LOCKED as Lang.String = "pin_locked";
private var mFailures as Lang.Array<Lang.Number>; private var mFailures as Lang.Array<Lang.Number>;
private var mLockedUntil as Lang.Number or Null; private var mLockedUntil as Lang.Number?;
//! Class Constructor //! Class Constructor
// //

View File

@ -49,8 +49,8 @@ class HomeAssistantService {
var entity_id; var entity_id;
var exit = false; var exit = false;
if (c != null) { if (c != null) {
entity_id = c.get(:entity_id) as Lang.String; entity_id = c[:entity_id] as Lang.String;
exit = c.get(:exit) as Lang.Boolean; exit = c[:exit] as Lang.Boolean;
} }
// System.println("HomeAssistantService onReturnCall() Response Code: " + responseCode); // System.println("HomeAssistantService onReturnCall() Response Code: " + responseCode);
// System.println("HomeAssistantService onReturnCall() Response Data: " + data); // System.println("HomeAssistantService onReturnCall() Response Data: " + data);
@ -125,7 +125,7 @@ class HomeAssistantService {
// //
function call( function call(
service as Lang.String, service as Lang.String,
data as Lang.Dictionary or Null, data as Lang.Dictionary?,
exit as Lang.Boolean exit as Lang.Boolean
) as Void { ) as Void {
var phoneConnected = System.getDeviceSettings().phoneConnected; var phoneConnected = System.getDeviceSettings().phoneConnected;

View File

@ -16,31 +16,35 @@
using Toybox.Communications; using Toybox.Communications;
using Toybox.Lang; using Toybox.Lang;
// SyncDelegate to execute single command via POST request to Home Assistant //! SyncDelegate to execute single command via POST request to the Home Assistant
//! server.
// //
class HomeAssistantSyncDelegate extends Communications.SyncDelegate { class HomeAssistantSyncDelegate extends Communications.SyncDelegate {
private static var syncError as Lang.String or Null; //! Retain the last synchronisation error.
private static var syncError as Lang.String?;
// Initialize an instance of this delegate //! Class Constructor
//
public function initialize() { public function initialize() {
SyncDelegate.initialize(); SyncDelegate.initialize();
} }
//! Called by the system to determine if a sync is needed //! Called by the system to determine if a synchronisation is needed
//
public function isSyncNeeded() as Lang.Boolean { public function isSyncNeeded() as Lang.Boolean {
return true; return true;
} }
//! Called by the system when starting a bulk sync. //! Called by the system when starting a bulk synchronisation.
//
public function onStartSync() as Void { public function onStartSync() as Void {
syncError = null; syncError = null;
if (WifiLteExecutionConfirmDelegate.mCommandData == null) { if (WifiLteExecutionConfirmDelegate.mCommandData == null) {
syncError = WatchUi.loadResource($.Rez.Strings.WifiLteExecutionDataError) as Lang.String; syncError = WatchUi.loadResource($.Rez.Strings.WifiLteExecutionDataError) as Lang.String;
onStopSync(); onStopSync();
return; return;
} }
var type = WifiLteExecutionConfirmDelegate.mCommandData[:type]; var type = WifiLteExecutionConfirmDelegate.mCommandData[:type];
var data = WifiLteExecutionConfirmDelegate.mCommandData[:data]; var data = WifiLteExecutionConfirmDelegate.mCommandData[:data];
var url; var url;
@ -65,8 +69,13 @@ class HomeAssistantSyncDelegate extends Communications.SyncDelegate {
} }
} }
// Performs a POST request to Hass with a given payload and URL, and calls haCallback //! Performs a POST request to the Home Assistant server with a given payload and URL, and calls
private function performRequest(url as Lang.String, data as Lang.Dictionary or Null) { //! haCallback.
//!
//! @param url URL for the API call.
//! @param data Data to be supplied to the API call.
//
private function performRequest(url as Lang.String, data as Lang.Dictionary?) {
Communications.makeWebRequest( Communications.makeWebRequest(
url, url,
data, // May include {"entity_id": xxxx} for service calls data, // May include {"entity_id": xxxx} for service calls
@ -83,12 +92,16 @@ class HomeAssistantSyncDelegate extends Communications.SyncDelegate {
} }
//! Handle callback from request //! Handle callback from request
public function haCallback(code as Lang.Number, data as Null or Lang.Dictionary) as Void { //!
//! @param responseCode Response code.
//! @param data Response data.
//
public function haCallback(code as Lang.Number, data as Lang.Dictionary?) as Void {
Communications.notifySyncProgress(100); Communications.notifySyncProgress(100);
if (code == 200) { if (code == 200) {
syncError = null; syncError = null;
if (WifiLteExecutionConfirmDelegate.mCommandData[:type].equals("entity")) { if (WifiLteExecutionConfirmDelegate.mCommandData[:type].equals("entity")) {
var callbackMethod = WifiLteExecutionConfirmDelegate.mCommandData[:callback]; var callbackMethod = WifiLteExecutionConfirmDelegate.mCommandData[:callback];
if (callbackMethod != null) { if (callbackMethod != null) {
var d = data as Lang.Array; var d = data as Lang.Array;
callbackMethod.invoke(d); callbackMethod.invoke(d);
@ -115,11 +128,11 @@ class HomeAssistantSyncDelegate extends Communications.SyncDelegate {
} }
//! Clean up //! Clean up
//
public function onStopSync() as Void { public function onStopSync() as Void {
if (WifiLteExecutionConfirmDelegate.mCommandData[:exit]) { if (WifiLteExecutionConfirmDelegate.mCommandData[:exit]) {
System.exit(); System.exit();
} }
Communications.cancelAllRequests(); Communications.cancelAllRequests();
Communications.notifySyncComplete(syncError); Communications.notifySyncComplete(syncError);
} }

View File

@ -21,11 +21,11 @@ using Toybox.Graphics;
// //
class HomeAssistantTapMenuItem extends HomeAssistantMenuItem { class HomeAssistantTapMenuItem extends HomeAssistantMenuItem {
private var mHomeAssistantService as HomeAssistantService; private var mHomeAssistantService as HomeAssistantService;
private var mService as Lang.String or Null; private var mService as Lang.String?;
private var mConfirm as Lang.Boolean; private var mConfirm as Lang.Boolean;
private var mExit as Lang.Boolean; private var mExit as Lang.Boolean;
private var mPin as Lang.Boolean; private var mPin as Lang.Boolean;
private var mData as Lang.Dictionary or Null; private var mData as Lang.Dictionary?;
//! Class Constructor //! Class Constructor
//! //!
@ -42,34 +42,34 @@ class HomeAssistantTapMenuItem extends HomeAssistantMenuItem {
//! one of these objects is created for all menu items to re-use. //! one of these objects is created for all menu items to re-use.
// //
function initialize( function initialize(
label as Lang.String or Lang.Symbol, label as Lang.String or Lang.Symbol,
template as Lang.String, template as Lang.String,
service as Lang.String or Null, service as Lang.String?,
data as Lang.Dictionary or Null, data as Lang.Dictionary?,
options as { options as {
:alignment as WatchUi.MenuItem.Alignment, :alignment as WatchUi.MenuItem.Alignment,
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol, :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol,
:exit as Lang.Boolean, :exit as Lang.Boolean,
:confirm as Lang.Boolean, :confirm as Lang.Boolean,
:pin as Lang.Boolean :pin as Lang.Boolean
} or Null, }?,
haService as HomeAssistantService haService as HomeAssistantService
) { ) {
HomeAssistantMenuItem.initialize( HomeAssistantMenuItem.initialize(
label, label,
template, template,
{ {
:alignment => options.get(:alignment), :alignment => options[:alignment],
:icon => options.get(:icon) :icon => options[:icon]
} }
); );
mHomeAssistantService = haService; mHomeAssistantService = haService;
mService = service; mService = service;
mData = data; mData = data;
mExit = options.get(:exit); mExit = options[:exit];
mConfirm = options.get(:confirm); mConfirm = options[:confirm];
mPin = options.get(:pin); mPin = options[:pin];
} }
//! Call a Home Assistant service only after checks have been done for confirmation or PIN entry. //! Call a Home Assistant service only after checks have been done for confirmation or PIN entry.
@ -92,7 +92,7 @@ class HomeAssistantTapMenuItem extends HomeAssistantMenuItem {
); );
} }
} else if (mConfirm) { } else if (mConfirm) {
var phoneConnected = System.getDeviceSettings().phoneConnected; var phoneConnected = System.getDeviceSettings().phoneConnected;
var internetAvailable = System.getDeviceSettings().connectionAvailable; var internetAvailable = System.getDeviceSettings().connectionAvailable;
if ((! phoneConnected || ! internetAvailable) && Settings.getWifiLteExecutionEnabled()) { if ((! phoneConnected || ! internetAvailable) && Settings.getWifiLteExecutionEnabled()) {
var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String;

View File

@ -39,14 +39,14 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
function initialize( function initialize(
label as Lang.String or Lang.Symbol, label as Lang.String or Lang.Symbol,
template as Lang.String, template as Lang.String,
data as Lang.Dictionary or Null, data as Lang.Dictionary?,
options as { options as {
:alignment as WatchUi.MenuItem.Alignment, :alignment as WatchUi.MenuItem.Alignment,
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol, :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol,
:exit as Lang.Boolean, :exit as Lang.Boolean,
:confirm as Lang.Boolean, :confirm as Lang.Boolean,
:pin as Lang.Boolean :pin as Lang.Boolean
} or Null }?
) { ) {
WatchUi.ToggleMenuItem.initialize( WatchUi.ToggleMenuItem.initialize(
label, label,
@ -54,8 +54,8 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
null, null,
false, false,
{ {
:alignment => options.get(:alignment), :alignment => options[:alignment],
:icon => options.get(:icon) :icon => options[:icon]
} }
); );
if (Attention has :vibrate) { if (Attention has :vibrate) {
@ -63,9 +63,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
} }
mData = data; mData = data;
mTemplate = template; mTemplate = template;
mExit = options.get(:exit); mExit = options[:exit];
mConfirm = options.get(:confirm); mConfirm = options[:confirm];
mPin = options.get(:pin); mPin = options[:pin];
} }
//! Set the state of a toggle menu item. //! Set the state of a toggle menu item.
@ -82,17 +82,17 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
//! Return the menu item's template. //! Return the menu item's template.
//! //!
//! @return A string with the menu item's template definition. //! @return A string with the menu item's template definition (or null).
// //
function getTemplate() as Lang.String or Null { function getTemplate() as Lang.String? {
return mTemplate; return mTemplate;
} }
//! Return a toggle menu item's state template. //! Return a toggle menu item's state template.
//! //!
//! @return A string with the menu item's template definition. //! @return A string with the menu item's template definition (or null).
// //
function getToggleTemplate() as Lang.String or Null { function getToggleTemplate() as Lang.String? {
return "{{states('" + mData.get("entity_id") + "')}}"; return "{{states('" + mData.get("entity_id") + "')}}";
} }
@ -218,7 +218,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
//! @param data An array of dictionaries, each representing a Home Assistant entity state. //! @param data An array of dictionaries, each representing a Home Assistant entity state.
// //
function setToggleStateWithData(data as Lang.Array) { function setToggleStateWithData(data as Lang.Array) {
// if there's no response body, let's assume that what we did, happened, and flip the toggle // If there's no response body, let's assume that what we did actually happened and flip the toggle.
if (data.size() == 0) { if (data.size() == 0) {
setEnabled(!isEnabled()); setEnabled(!isEnabled());
} }
@ -267,8 +267,8 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
url, url,
mData, mData,
{ {
:method => Communications.HTTP_REQUEST_METHOD_POST, :method => Communications.HTTP_REQUEST_METHOD_POST,
:headers => { :headers => {
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON, "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON,
"Authorization" => "Bearer " + Settings.getApiKey() "Authorization" => "Bearer " + Settings.getApiKey()
}, },
@ -348,11 +348,10 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
//! @param s Desired state: `true` to turn on, `false` to turn off. //! @param s Desired state: `true` to turn on, `false` to turn off.
// //
private function wifiPrompt(s as Lang.Boolean) as Void { private function wifiPrompt(s as Lang.Boolean) as Void {
var id = mData.get("entity_id") as Lang.String; var id = mData.get("entity_id") as Lang.String;
var url = getUrl(id, s); var url = getUrl(id, s);
var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String;
var dialog = new WatchUi.Confirmation(dialogMsg); var dialog = new WatchUi.Confirmation(dialogMsg);
WatchUi.pushView( WatchUi.pushView(
dialog, dialog,
new WifiLteExecutionConfirmDelegate({ new WifiLteExecutionConfirmDelegate({
@ -374,7 +373,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
//! //!
//! @return Full service URL string. //! @return Full service URL string.
// //
private function getUrl(id as Lang.String, s as Lang.Boolean) as Lang.String { private static function getUrl(id as Lang.String, s as Lang.Boolean) as Lang.String {
var url = Settings.getApiUrl() + "/services/"; var url = Settings.getApiUrl() + "/services/";
if (s) { if (s) {
url = url + id.substring(0, id.find(".")) + "/turn_on"; url = url + id.substring(0, id.find(".")) + "/turn_on";

View File

@ -30,7 +30,7 @@ class HomeAssistantView extends WatchUi.Menu2 {
options as { options as {
:focus as Lang.Number, :focus as Lang.Number,
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
} or Null }?
) { ) {
if (options == null) { if (options == null) {
options = { :title => definition.get("title") as Lang.String }; options = { :title => definition.get("title") as Lang.String };
@ -42,17 +42,17 @@ class HomeAssistantView extends WatchUi.Menu2 {
var items = definition.get("items") as Lang.Array<Lang.Dictionary>; var items = definition.get("items") as Lang.Array<Lang.Dictionary>;
for (var i = 0; i < items.size(); i++) { for (var i = 0; i < items.size(); i++) {
if (items[i] instanceof(Lang.Dictionary)) { if (items[i] instanceof(Lang.Dictionary)) {
var type = items[i].get("type") as Lang.String or Null; var type = items[i].get("type") as Lang.String?;
var name = items[i].get("name") as Lang.String or Null; var name = items[i].get("name") as Lang.String?;
var content = items[i].get("content") as Lang.String or Null; var content = items[i].get("content") as Lang.String?;
var entity = items[i].get("entity") as Lang.String or Null; var entity = items[i].get("entity") as Lang.String?;
var tap_action = items[i].get("tap_action") as Lang.Dictionary or Null; var tap_action = items[i].get("tap_action") as Lang.Dictionary?;
var service = items[i].get("service") as Lang.String or Null; // Deprecated schema var service = items[i].get("service") as Lang.String?; // Deprecated schema
var confirm = false as Lang.Boolean or Null; var confirm = false as Lang.Boolean?;
var pin = false as Lang.Boolean or Null; var pin = false as Lang.Boolean?;
var data = null as Lang.Dictionary or Null; var data = null as Lang.Dictionary?;
var enabled = true as Lang.Boolean or Null; var enabled = true as Lang.Boolean?;
var exit = false as Lang.Boolean or Null; var exit = false as Lang.Boolean?;
if (items[i].get("enabled") != null) { if (items[i].get("enabled") != null) {
enabled = items[i].get("enabled"); // Optional enabled = items[i].get("enabled"); // Optional
} }
@ -207,7 +207,7 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate {
mTimer = getApp().getQuitTimer(); mTimer = getApp().getQuitTimer();
} }
//! Back button event //! Handle the back button (ESC)
// //
function onBack() { function onBack() {
mTimer.reset(); mTimer.reset();

View File

@ -42,7 +42,7 @@ class Settings {
private static var mPollDelay as Lang.Number = 0; private static var mPollDelay as Lang.Number = 0;
//! seconds //! seconds
private static var mConfirmTimeout as Lang.Number = 3; private static var mConfirmTimeout as Lang.Number = 3;
private static var mPin as Lang.String or Null = "0000"; private static var mPin as Lang.String? = "0000";
private static var mMenuAlignment as Lang.Number = WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_LEFT; private static var mMenuAlignment as Lang.Number = WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_LEFT;
private static var mIsSensorsLevelEnabled as Lang.Boolean = false; private static var mIsSensorsLevelEnabled as Lang.Boolean = false;
//! minutes //! minutes
@ -50,7 +50,7 @@ class Settings {
private static var mIsApp as Lang.Boolean = false; private static var mIsApp as Lang.Boolean = false;
private static var mHasService as Lang.Boolean = false; private static var mHasService as Lang.Boolean = false;
//! Must keep the object so it doesn't get garbage collected. //! Must keep the object so it doesn't get garbage collected.
private static var mWebhookManager as WebhookManager or Null; private static var mWebhookManager as WebhookManager?;
//! Called on application start and then whenever the settings are changed. //! Called on application start and then whenever the settings are changed.
// //
@ -229,7 +229,7 @@ class Settings {
//! //!
//! @return The menu item security PIN. //! @return The menu item security PIN.
// //
static function getPin() as Lang.String or Null { static function getPin() as Lang.String? {
return mPin; return mPin;
} }
@ -237,7 +237,7 @@ class Settings {
//! //!
//! @return The validated 4 digit string. //! @return The validated 4 digit string.
// //
private static function validatePin() as Lang.String or Null { private static function validatePin() as Lang.String? {
var pin = Properties.getValue("pin"); var pin = Properties.getValue("pin");
if (pin.toNumber() == null || pin.length() != 4) { if (pin.toNumber() == null || pin.length() != 4) {
return null; return null;

View File

@ -71,7 +71,7 @@ class WebhookManager {
case 200: case 200:
case 201: case 201:
var id = data.get("webhook_id") as Lang.String or Null; var id = data.get("webhook_id") as Lang.String?;
if (id != null) { if (id != null) {
Settings.setWebhookId(id); Settings.setWebhookId(id);
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering first sensor: Battery Level"); // System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering first sensor: Battery Level");
@ -177,7 +177,7 @@ class WebhookManager {
case 201: case 201:
if (data instanceof Lang.Dictionary) { if (data instanceof Lang.Dictionary) {
var d = data as Lang.Dictionary; var d = data as Lang.Dictionary;
var b = d.get("success") as Lang.Boolean or Null; var b = d.get("success") as Lang.Boolean?;
if (b != null and b != false) { if (b != null and b != false) {
if (sensors.size() == 0) { if (sensors.size() == 0) {
getApp().startUpdates(); getApp().startUpdates();

View File

@ -19,40 +19,47 @@ using Toybox.Communications;
using Toybox.Lang; using Toybox.Lang;
using Toybox.Timer; using Toybox.Timer;
// Delegate to respond to a confirmation to execute command via bulk sync //! Delegate to respond to a confirmation to execute an API request via bulk
//! synchronisation.
// //
class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
public static var mCommandData as { public static var mCommandData as {
:type as Lang.String, :type as Lang.String,
:service as Lang.String or Null, :service as Lang.String?,
:data as Lang.Dictionary or Null, :data as Lang.Dictionary?,
:url as Lang.String or Null, :url as Lang.String?,
:id as Lang.Number or Null, :id as Lang.Number?,
:exit as Lang.Boolean :exit as Lang.Boolean
}; };
private static var mTimer as Timer.Timer or Null; private static var mTimer as Timer.Timer?;
private var mHasToast as Lang.Boolean = false; private var mHasToast as Lang.Boolean = false;
private var mConfirmationView as WatchUi.Confirmation; private var mConfirmationView as WatchUi.Confirmation;
//! Initializes a confirmation delegate to confirm a Wi-Fi or LTE command exection //! Initializes a confirmation delegate to confirm a Wi-Fi or LTE command execution
//! //!
//! @param options A dictionary describing the command to be executed: //! @param options A dictionary describing the command to be executed:<br>
//! - type: The command type, either `"service"` or `"entity"`. //! `{`<br>
//! - service: (For type `"service"`) The Home Assistant service to call (e.g., "light.turn_on"). //! &emsp; `:type: as Lang.String,` // The command type, either `"service"` or `"entity"`.<br>
//! - url: (For type `"entity"`) The full Home Assistant entity API URL. //! &emsp; `:service: as Lang.String?,` // (For type `"service"`) The Home Assistant service to call (e.g., "light.turn_on").<br>
//! - callback: (For type `"entity"`) A callback method (Method<data as Dictionary>) to handle the response. //! &emsp; `:url: as Lang.Dictionary?,` // (For type `"entity"`) The full Home Assistant entity API URL.<br>
//! - data: (Optional) A dictionary of data to send with the request. //! &emsp; `:callback: as Lang.String?,` // (For type `"entity"`) A callback method (Method<data as Dictionary>) to handle the response.<br>
//! - exit: Boolean: if set to true: exit after running command. //! &emsp; `:data: as Lang.Method?,` // (Optional) A dictionary of data to send with the request.<br>
//! &emsp; `:exit: as Lang.Boolean,` // Boolean: if set to true: exit after running command.<br>
//! &rbrace;<br>
//! @param view The Confirmation view the delegate is active for //! @param view The Confirmation view the delegate is active for
function initialize(cOptions as { //
:type as Lang.String, function initialize(
:service as Lang.String or Null, cOptions as {
:data as Lang.Dictionary or Null, :type as Lang.String,
:url as Lang.String or Null, :service as Lang.String?,
:callback as Lang.Method or Null, :data as Lang.Dictionary?,
:exit as Lang.Boolean, :url as Lang.String?,
}, view as WatchUi.Confirmation) { :callback as Lang.Method?,
:exit as Lang.Boolean,
},
view as WatchUi.Confirmation
) {
ConfirmationDelegate.initialize(); ConfirmationDelegate.initialize();
if (mTimer != null) { if (mTimer != null) {
@ -65,12 +72,12 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
mConfirmationView = view; mConfirmationView = view;
mCommandData = { mCommandData = {
:type => cOptions[:type], :type => cOptions[:type],
:service => cOptions[:service], :service => cOptions[:service],
:data => cOptions[:data], :data => cOptions[:data],
:url => cOptions[:url], :url => cOptions[:url],
:callback => cOptions[:callback], :callback => cOptions[:callback],
:exit => cOptions[:exit] :exit => cOptions[:exit]
}; };
var timeout = Settings.getConfirmTimeout(); // ms var timeout = Settings.getConfirmTimeout(); // ms
@ -78,7 +85,6 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
if (mTimer == null) { if (mTimer == null) {
mTimer = new Timer.Timer(); mTimer = new Timer.Timer();
} }
mTimer.start(method(:onTimeout), timeout, true); mTimer.start(method(:onTimeout), timeout, true);
} }
} }
@ -87,6 +93,7 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
//! //!
//! @param response The user's confirmation response as `WatchUi.Confirm` //! @param response The user's confirmation response as `WatchUi.Confirm`
//! @return Always returns `true` to indicate the response was handled. //! @return Always returns `true` to indicate the response was handled.
//
function onResponse(response) as Lang.Boolean { function onResponse(response) as Lang.Boolean {
getApp().getQuitTimer().reset(); getApp().getQuitTimer().reset();
if (mTimer != null) { if (mTimer != null) {
@ -100,15 +107,15 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
} }
//! Initiates a bulk sync process to execute a command, if connections are available //! Initiates a bulk sync process to execute a command, if connections are available
//
private function trySync() as Void { private function trySync() as Void {
var connectionInfo = System.getDeviceSettings().connectionInfo; var connectionInfo = System.getDeviceSettings().connectionInfo;
var keys = connectionInfo.keys(); var keys = connectionInfo.keys();
var possibleConnection = false; var possibleConnection = false;
for(var i = 0; i < keys.size(); i++) { for(var i = 0; i < keys.size(); i++) {
if (keys[i] != :bluetooth) { if (keys[i] != :bluetooth) {
var connection = connectionInfo[keys[i]]; if (connectionInfo[keys[i]].state != System.CONNECTION_STATE_NOT_INITIALIZED) {
if (connection.state != System.CONNECTION_STATE_NOT_INITIALIZED) {
possibleConnection = true; possibleConnection = true;
break; break;
} }
@ -117,8 +124,9 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
if (possibleConnection) { if (possibleConnection) {
if (Communications has :startSync2) { if (Communications has :startSync2) {
var syncString = WatchUi.loadResource($.Rez.Strings.WifiLteExecutionTitle) as Lang.String; Communications.startSync2({
Communications.startSync2({:message => syncString}); :message => WatchUi.loadResource($.Rez.Strings.WifiLteExecutionTitle) as Lang.String
});
} else { } else {
Communications.startSync(); Communications.startSync();
} }
@ -139,6 +147,7 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate {
} }
//! Function supplied to a timer in order to limit the time for which the confirmation can be provided. //! Function supplied to a timer in order to limit the time for which the confirmation can be provided.
//
function onTimeout() as Void { function onTimeout() as Void {
mTimer.stop(); mTimer.stop();
var getCurrentView = WatchUi.getCurrentView(); var getCurrentView = WatchUi.getCurrentView();