For my first app, I want to make a widget that, when viewed, sends an update to a Slack channel about how far I've run and how far away I am from the office. To do this, I started with the simple watchface sample app and have been adding my makeWebRequest code to function onShow() in the file helloView.mc.
I am currently setting variables for each argument of the request:
function onShow() {
var url = "hooks.slack.com/.../vR0y2342wGe234few2OQ0xHe";
var params = {
"channel" => "#dev",
"username" => "ram-bot",
"text" => "test garmin slack integration",
"icon_emoji" => ":athletic_shoe:"
};
var headers = {
"Content-Type" => Comm.REQUEST_CONTENT_TYPE_URL_ENCODED,
"Accept" => "application/json"
};
var options = {
:method => Comm.HTTP_REQUEST_METHOD_POST,
:headers => headers
};
And then I have the actual request code, and it's commented out for now:
// Comm.makeWebRequest(
// url, params, options, method(:onReceive)
// );
But even with just that, my app doesn't run in the simulator and I get the following console output:
File pushed successfully
Connection Finished
Closing shell and port
Found Transport: tcp
Connecting...
Connecting to device...
Device Version 0.1.0
Device id 1 name "A garmin device"
Shell Version 0.1.0
Permission required
Permission Required
Failed invoking <symbol>
Connection Finished
Closing shell and port
I am trying to run this on a Forerunner920XT and I am working in Eclipse on a Mac. I see that permission required usually means you are trying to access an API that is not available, is there something about setting variables that wouldn't be allowed in this file/function?
Here's the full code for the project for context:
helloView.mc
using Toybox.WatchUi as Ui;
using Toybox.Graphics as Gfx;
using Toybox.System as Sys;
using Toybox.Lang as Lang;
using Toybox.Application as App;
using Toybox.Communications as Comm;
class helloView extends Ui.WatchFace {
function initialize() {
WatchFace.initialize();
}
// Load your resources here
function onLayout(dc) {
setLayout(Rez.Layouts.WatchFace(dc));
}
// 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() {
var url = "hooks.slack.com/.../vR0yM234RwGeT69tGaOQ0xHe";
var params = {
"channel" => "#dev",
"username" => "ram-bot",
"text" => "test garmin slack integration",
"icon_emoji" => ":athletic_shoe:"
};
var headers = {
"Content-Type" => Comm.REQUEST_CONTENT_TYPE_URL_ENCODED,
"Accept" => "application/json"
};
var options = {
:method => Comm.HTTP_REQUEST_METHOD_POST,
:headers => headers
};
// Comm.makeWebRequest(
// url, params, options, method(:onReceive)
// );
}
// Update the view
function onUpdate(dc) {
// Get the current time and format it correctly
var timeFormat = "$1$:$2$";
var clockTime = Sys.getClockTime();
var hours = clockTime.hour;
if (!Sys.getDeviceSettings().is24Hour) {
if (hours > 12) {
hours = hours - 12;
}
} else {
if (App.getApp().getProperty("UseMilitaryFormat")) {
timeFormat = "$1$$2$";
hours = hours.format("%02d");
}
}
var timeString = Lang.format(timeFormat, [hours, clockTime.min.format("%02d")]);
// Update the view
var view = View.findDrawableById("TimeLabel");
view.setColor(App.getApp().getProperty("ForegroundColor"));
view.setText(timeString+"\nhello world");
// Call the parent onUpdate function to redraw the layout
View.onUpdate(dc);
}
// Called when this View is removed from the screen. Save the
// state of this View here. This includes freeing resources from
// memory.
function onHide() {
}
// The user has just looked at their watch. Timers and animations may be started here.
function onExitSleep() {
}
// Terminate any active timers and prepare for slow updates.
function onEnterSleep() {
}
}
helloApp.mc
using Toybox.Application as App;
using Toybox.WatchUi as Ui;
class helloApp extends App.AppBase {
function initialize() {
AppBase.initialize();
}
// onStart() is called on application start up
function onStart(state) {
}
// onStop() is called when your application is exiting
function onStop(state) {
}
// Return the initial view of your application here
function getInitialView() {
return [ new helloView() ];
}
// New app settings have been received so trigger a UI update
function onSettingsChanged() {
Ui.requestUpdate();
}
}
helloBackgound.mc
using Toybox.WatchUi as Ui;
using Toybox.Application as App;
using Toybox.Graphics as Gfx;
class Background extends Ui.Drawable {
function initialize() {
var dictionary = {
:identifier => "Background"
};
Drawable.initialize(dictionary);
}
function draw(dc) {
// Set the background color then call to clear the screen
dc.setColor(Gfx.COLOR_TRANSPARENT, App.getApp().getProperty("BackgroundColor"));
dc.clear();
}
}
Any help is greatly appreciated!!