Feature Request - Simulator

Please add a dashboard which allows to change sensor values, like the compass heading (by using a slider gadget). And don't use a modal window for this dialog so that the main window showing the watch display could be brought on top.
  • Have you looked into recording a .fit and playing it back in the sim? Different scenarios for what you want to test? You record with the sensors you want, using actual data or get .fit files from others for their specific case, etc.

    It's quite handy, and also easily repeatable if you're fixing bugs, etc.
  • Some things have to be done interactive, I am working to implement a feature to set options in a datafield just by using the watch...
    ...the idea is, that the watch checks before the activity timer gets started, if you make a 180 degree turn. After doing so, an option could be changed by rotating the watch. I made a widget for testing, but had to transfer it multiple times to the watch, because the simulator can't do such things...

    using Toybox.Application as App;
    using Toybox.System as Sys;
    using Toybox.Time as Time;
    using Toybox.Time.Gregorian as Gregorian;
    using Toybox.Lang as Lang;
    using Toybox.Math as Math;
    using Toybox.WatchUi as Ui;
    using Toybox.Graphics as Gfx;
    using Toybox.Attention as Attention;

    var mode=0;
    var config=0;

    class MyView extends Ui.View
    {
    var timer;
    var target;
    var now;
    var demo=0;
    var counter=0;

    const Radiant=180.0/Math.PI;

    function initialize()
    { // Sys.println("* MyView Init");
    Ui.View.initialize();
    timer=new Timer.Timer();
    timer.start(method(:callback),250,true);

    mode=0;
    target=0;
    Ui.requestUpdate();
    }

    function callback()
    { // Sys.println("* MyDelegate Timer ("+menu+")");
    Ui.requestUpdate();
    }

    function symbol(dc,pos,symbol,bit)
    {
    pos=pos%360;

    if (pos>=170 && pos<190) // Z (20 Grad pro Button)
    { dc.setColor(Gfx.COLOR_GREEN,-1);
    Attention.backlight(true); // Licht an...
    if (bit+1)
    { if ( mode&(15<<bit) == mode )
    { mode+=(1<<bit); }
    else
    { mode=1<<bit; }
    }
    }
    else
    { dc.setColor(Gfx.COLOR_BLACK,-1); }

    pos/=5; // A ( Schrittweise scrollen )
    pos*=20; // B ( B = C/Z*A )
    pos-=640; // 180/A*B-sx/2+C/2

    dc.fillRectangle(pos,42,80,38); // C (Breite Button)
    dc.setColor(Gfx.COLOR_WHITE,-1);
    dc.drawRectangle(pos+2,44,76,34);
    dc.drawText(pos+40,43,Gfx.FONT_MEDIUM,symbol,Gfx.TEXT_JUSTIFY_CENTER);
    }

    function onUpdate(dc)
    { // Sys.println("* MyView Update");

    dc.setColor(Gfx.COLOR_WHITE,0x000055);
    dc.clear();
    dc.setColor(Gfx.COLOR_WHITE,-1);

    var ActInfo = Activity.getActivityInfo();
    if (ActInfo != null)
    { now=(ActInfo.currentHeading*Radiant).toNumber();
    demo+=3;
    //now=demo;
    if (mode==0)
    { target=now; mode=1; }
    else if (mode>1 && mode<16)
    { config=1; }

    var title;
    if (config)
    { title="SET VALUE"; }
    else
    { title="READY"; }
    dc.drawText(120,170,Gfx.FONT_MEDIUM,title,Gfx.TEXT_JUSTIFY_CENTER);

    now=360+target-now;

    if (config)
    { symbol(dc,now,"ok",0);
    symbol(dc,now-25,"-",8);
    symbol(dc,now+25,"+",4);
    }
    else
    { symbol(dc,now,"set",0); }


    if (mode==12)
    { // Sys.println("COUNTER SET "+counter);
    dc.setColor(Gfx.COLOR_GREEN,-1);
    mode=0;
    config=0;
    }
    else if (mode==16*6)
    { // Sys.println("COUNTER (+) "+(counter+1));
    // dc.setColor(Gfx.COLOR_YELLOW,-1);
    counter+=1;
    mode=16;
    }
    else if (mode==256*6)
    { // Sys.println("COUNTER (-) "+(counter-1));
    // dc.setColor(Gfx.COLOR_YELLOW,-1);
    counter-=1;
    mode=256;
    }
    else
    { dc.setColor(Gfx.COLOR_WHITE,-1); }

    dc.drawText(120,90,Gfx.FONT_NUMBER_HOT,counter,Gfx.TEXT_JUSTIFY_CENTER);

    }
    else
    {
    dc.drawText(120,120,Gfx.FONT_LARGE,": (",Gfx.TEXT_JUSTIFY_CENTER);
    }

    }
    }

    class MyBehaviour extends Ui.BehaviorDelegate
    {
    function initialize()
    { Sys.println("* MyDelegate INIT *");
    Ui.BehaviorDelegate.initialize();
    }

    function onMenu()
    { Sys.println("* MyDelegate MENU *");
    return true;
    }

    function onSelect()
    { Sys.println("* MyDelegate START *");
    mode=0;
    config=1;
    Ui.requestUpdate();
    return true;
    }

    }


    class Test extends App.AppBase
    {
    function initialize() { App.AppBase.initialize(); }
    function onStart(state) { }
    function onStop(state) { }
    function onMenu(state) { }
    function getInitialView() { return [new MyView(), new MyBehaviour()]; }
    }
  • Have you looked at using app-settings for this? Sounds like you want a complex change for kind of a unique situation.

    Before app settings, folks were trying to make things configurable by setting uniq weight/height, entering/leaving the app a certain number of times during a certain amount of time, etc.

    App-settings did away with that. Now you just set things using your phone. Easier, and less error prone. Also, you need very little code in an app to make use of app settings.
  • Did not look into that s far, because I don't like the Connect IQ app (which is battery, memory and time wasting - would like to have a small core ap just handling the notifications) and my sport activities are done without any phone or internet access.
    I know my approach for the datafield settings is a little bit crazy - but inedependly to that, the simulator would help a lot in different situations if some sliders (pace, heartrate, compass heading etc.) could be used to simply set values for testing...