*Your Tesla account information is stored on your device and only transmitted to authenticate with your vehicle to get a key from Tesla once in a while.
1466 |
1472 |
1473 |
1474 |
1475 |
1476 | `
1477 |
1478 | // WebView
1479 | WebView.loadHTML(html, null, new Size(0, 100));
1480 |
1481 | }
1482 |
1483 |
1484 |
1485 |
1486 | function themeDebugArea(){
1487 | // This is a working area for theme development (so errors will give you correct line numbers
1488 | // Once you've finished, move your code to a JS file in the tesla_data folder
1489 |
1490 |
1491 |
1492 |
1493 |
1494 |
1495 |
1496 |
1497 | }
1498 |
1499 |
--------------------------------------------------------------------------------
/documentation/Developers.md:
--------------------------------------------------------------------------------
1 | # Rough theme development overveiw
2 |
3 | In general, you should use themes for any customization you want to do to the display or data. Refer to the [Scriptable documentation](https://scriptable.app/) for relavant javascript functions.
4 |
5 | ## colors
6 |
7 | The easiest way to theme the widget is to modify the colors. This can be done by overriding the colors used in the theme file:
8 |
9 | colors.background:"#ddbbbb";
10 |
11 | Colors should be hex colors, RRGGBBAA (red, green, blue, alpha) or RRGGBB (red, green, blue). RGB (red, green, blue) is valid, but there's a bug in Scriptable where green and blue are swapped. It's recommended not to use this format.
12 |
13 | ## car_data.postLoad(json)
14 |
15 | The postLoad function can be overwritten so you can consume additional data from your json file and modify (or add) variables to the car_data object. For instance, you may wish to grab your car's color and add it to car_data:
16 |
17 |
18 | car_data.postLoad = function (json){
19 | var this.car_color = json.exterior_color;
20 | var colors.car_color = "#ffffff";
21 | switch (this.car_color){
22 | case "deepBlue":
23 | colors.car_color = "#0000ff";
24 | break;
25 | }
26 | }
27 |
28 | ## Theme
29 |
30 | The theme object is called to draw the data to the widget. Themes are broken down into small, medium, and large (so you can write a theme that supports all three sizes). A theme.[size].available variable is set to let the system know if the theme is available in that size.
31 |
32 | You can override the theme's draw function to completely change the way that the widget is drawn. This should be done by replacing the theme.small.draw function.
33 |
34 | However, if you want to use the existing theme, but change certain parts, the existing theme is split into 5 boxes that are stacked vertically: Car Status, Car Name, Status Lights, Range Info, and Battery Bar. You can override any of these functions to provide your own style.
35 |
36 | For instance, if you wanted to change the way that the car's name is displayed, you can override the drawCarName function:
37 |
38 | theme.drawCarName = function (widget, car_data, colors){
39 | let stack = widget.addStack();
40 | stack.size = new Size(widgetSize.width,widgetSize.height*0.25);
41 | stack.centerAlignContent();
42 | stack.setPadding(0,3,5,3);
43 |
44 | let carName = stack.addText(car_data.car_name);
45 | carName.textColor = new Color(colors.text.primary);
46 | carName.leftAlignText() // align the text left instead of center
47 | carName.font = Font.semiboldSystemFont(24)
48 | carName.minimumScaleFactor = 0.5
49 | }
50 |
51 | ## Icons
52 |
53 | Iconography is broken into separate functions as well, so you can override one of these functions to change the icon used to draw for certain states:
54 |
55 | theme.getSleepingIcon = function(colors){
56 | symbolToUse = "zzz"; // change from moon.zzz.fill to a plain zzz icon
57 | let statusSymbol = SFSymbol.named(symbolToUse);
58 | return statusSymbol.image;
59 | }
60 |
61 | ## Battery Bar
62 |
63 | You can review the themes directory to see the way that the 3d.js file restyles the battery bar. The battery bar is its own object that you can modify. You can replace the entire draw function to create a different style battery bar. The function must return an image.
64 |
--------------------------------------------------------------------------------
/documentation/config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/config.png
--------------------------------------------------------------------------------
/documentation/json_requirements.md:
--------------------------------------------------------------------------------
1 | # Overview of the fields in that are consumed by the widget.
2 |
3 | ## Required
4 | * usable_battery_level : the actual usable amount (0-100), this is used when the battery is cold
5 | * charge_limit_soc : the charge limit you have configured for the car (0-100)
6 |
7 | Although, it's a good idea to include all of the following fields, the widget will still render what it can when you include any of the following fields.
8 |
9 | ## Optional
10 | * response : should be null unless there is an error
11 | * Date : the last contact with the vehicle (This can be almost any date format, but should include date and time, TelsaFi uses UTC style YYYY-MM-DD HH:MM:SS)
12 | * battery_level : the current battery value (0-100)
13 | * carState : the current state of the car (Sleeping, Charging, Driving, Idle)
14 | * sentry_mode : is sentry mode on (0 or 1)
15 | * display_name : the name of the car (as defined by the user)
16 | * locked : are the doors locked (0 or 1)
17 | * is_climate_on : is the car's climate system on (0 or 1)
18 | * inside_temp : the inside temperature of the car in C
19 | * driver_temp_setting : the set temp for the climate control in C
20 | * temperature : if we should display F or C temperatures
21 | * inside_tempF : the inside temperature of the car in F (only used if temperature == F)
22 | * driver_temp_settingF : the set temp for the climate control in F (only used if temperature == F)
23 | * measure : if the range/distance measurements are in km or m
24 | * battery_range : the range of the car (as calculated by the car)
25 | * est_battery_range : the range of the car (as calculated by the logging service)
26 | * time_to_full_charge : how long until the car is fully charged
27 | * fast_charger_type : what kind of charger is attached. Should be "" if the car is not connected to a charger (the widget only checks to see if it's attached, so the actual type is unimportant).
28 | * latitude : the latitude location of the car
29 | * longitude : the longitude location of the car
30 |
--------------------------------------------------------------------------------
/documentation/sample.json:
--------------------------------------------------------------------------------
1 | {
2 | "response":null,
3 | "battery_level":27,
4 | "usable_battery_level":26,
5 | "charge_limit_soc":90,
6 | "carState":"Idling",
7 | "Date":"2020-10-28T14:57:15Z",
8 | "sentry_mode":0,
9 | "display_name":"Name",
10 | "locked":1,
11 | "is_climate_on":0,
12 | "inside_temp":14.6,
13 | "driver_temp_setting":22.0,
14 | "measure":"km",
15 | "est_battery_range":90.605842,
16 | "battery_range":125.2227454,
17 | "time_to_full_charge":0.0,
18 | "fast_charger_type":""
19 | }
20 |
--------------------------------------------------------------------------------
/documentation/screen_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_001.png
--------------------------------------------------------------------------------
/documentation/screen_001_med.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_001_med.png
--------------------------------------------------------------------------------
/documentation/screen_002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_002.png
--------------------------------------------------------------------------------
/documentation/screen_003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_003.png
--------------------------------------------------------------------------------
/documentation/screen_3d_002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_3d_002.png
--------------------------------------------------------------------------------
/documentation/screen_3d_003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_3d_003.png
--------------------------------------------------------------------------------
/documentation/screen_map_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DrieStone/TeslaData-Widget/db0b661fb7cdf46a4b26c8f442818bb68ccdebb5/documentation/screen_map_001.png
--------------------------------------------------------------------------------
/documentation/theme_listing.md:
--------------------------------------------------------------------------------
1 | # Listing of themes available
2 |
3 | ## 3D Bar
4 |
5 | Shows the battery bar in a 3D style.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/documentation/version.js:
--------------------------------------------------------------------------------
1 | // this is a remote file that is loaded in the configuration to notify the user if there is a new version of the widget available
2 | online_version = 1.7;
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tesla_data/3d.js:
--------------------------------------------------------------------------------
1 |
2 | colors.battery.border_3d = "#33333333";
3 |
4 | battery_bar.draw = function(car_data,colors){
5 | let myDrawContext = new DrawContext();
6 | myDrawContext.opaque = false;
7 | myDrawContext.size = new Size(this.width+2,this.height+2);
8 |
9 | // draw the background
10 | myDrawContext.addPath(this.batteryPath);
11 | myDrawContext.setFillColor(new Color(colors.battery.background));
12 | myDrawContext.fillPath();
13 |
14 | // draw the max charge (as set by the user)
15 | let batteryMaxCharge = new DrawContext() ;
16 | batteryMaxCharge.opaque = false;
17 | batteryMaxCharge.size = new Size(this.width*car_data.battery_limit/100,this.height)
18 | if (car_data.car_state == "Charging"){
19 | batteryMaxCharge.setFillColor(new Color(colors.battery.charging));
20 | } else {
21 | batteryMaxCharge.setFillColor(new Color(colors.battery.max_charge));
22 | }
23 | batteryMaxCharge.addPath(this.batteryPath);
24 | batteryMaxCharge.fillPath();
25 |
26 | myDrawContext.drawImageAtPoint(batteryMaxCharge.getImage(),new Point(0,0));
27 |
28 | let usable_battery_level = Number(car_data.usable_battery_level);
29 |
30 | // draw the cold battery (if needed)
31 | if (usable_battery_level < car_data.battery_level && car_data.battery_level > 1){
32 | let unavailableCharge = new DrawContext() ;
33 | unavailableCharge.opaque = false;
34 | unavailableCharge.size = new Size(this.width*car_data.battery_level/100,this.height);
35 |
36 | unavailableCharge.setFillColor(new Color(colors.battery.cold_charge));
37 | unavailableCharge.addPath(this.batteryPath);
38 | unavailableCharge.fillPath();
39 |
40 | myDrawContext.drawImageAtPoint(unavailableCharge.getImage(),new Point(0,0));
41 |
42 | usable_battery_level -= 2; // shave a little off so the cold battery display isn't just a sliver of blue.
43 | }
44 |
45 |
46 | myDrawContext.addPath(this.batteryPathInset);
47 | myDrawContext.setStrokeColor(new Color(colors.battery.border_3d,0.3));
48 | myDrawContext.setLineWidth(4);
49 | myDrawContext.strokePath();
50 |
51 |
52 | // draw the available charge
53 | if (usable_battery_level>1){
54 | // if there's at least some battery, build the current charge state bar
55 | let availableCharge = new DrawContext() ;
56 | availableCharge.opaque = false;
57 | availableCharge.size = new Size(this.width*usable_battery_level/100,this.height);
58 |
59 | availableCharge.setFillColor(new Color(colors.battery.usable_charge));
60 | availableCharge.addPath(this.batteryPath);
61 | availableCharge.fillPath();
62 |
63 | this.drawHighlight(availableCharge,this.width*usable_battery_level/100,colors);
64 |
65 | availableCharge.addPath(this.batteryPathInset);
66 | availableCharge.setStrokeColor(new Color(colors.battery.border_3d,0.7));
67 | availableCharge.setLineWidth(2);
68 | availableCharge.strokePath();
69 |
70 |
71 | myDrawContext.drawImageAtPoint(availableCharge.getImage(),new Point(0,0));
72 | }
73 |
74 | if (Number(car_data.battery_level)<99){
75 | myDrawContext.setFillColor(new Color(colors.battery.separator));
76 | myDrawContext.fillRect(new Rect(this.width*car_data.battery_level/100,1,1,this.height-1));
77 | if (usable_battery_level < car_data.battery_level){
78 | myDrawContext.fillRect(new Rect(this.width*usable_battery_level/100,1,1,this.height-1))
79 | }
80 |
81 | myDrawContext.setFillColor(new Color(colors.battery.border_3d,0.7));
82 | myDrawContext.fillRect(new Rect(this.width*car_data.battery_level/100+1,1,3,this.height-1))
83 |
84 | }
85 |
86 |
87 | // add a final stroke to the whole thing
88 | myDrawContext.addPath(this.batteryPath);// have to add the path again for some reason
89 | myDrawContext.setStrokeColor(new Color(colors.battery.border));
90 | myDrawContext.setLineWidth(1);
91 | myDrawContext.strokePath();
92 |
93 | return myDrawContext.getImage(); // return our final image
94 |
95 | }
96 |
97 |
98 | battery_bar.drawHighlight =function(contextToDrawOn,width,colors){
99 | width = width - 10;
100 | if (width > 4){
101 | const batteryHighlight = new Path();
102 | batteryHighlight.addRoundedRect(new Rect(5,6,width+2,3),1,1);
103 |
104 | contextToDrawOn.setFillColor(new Color(colors.battery.highlight,0.3));
105 | contextToDrawOn.addPath(batteryHighlight);
106 | contextToDrawOn.fillPath();
107 |
108 | contextToDrawOn.setFillColor(new Color(colors.battery.highlight,0.3));
109 | contextToDrawOn.fillEllipse(new Rect(7,6,width/4,4));
110 | contextToDrawOn.fillEllipse(new Rect(6,6,width/8,6));
111 | contextToDrawOn.fillEllipse(new Rect(5,6,width/12,8));
112 |
113 | contextToDrawOn.fillEllipse(new Rect(width,6,5,3)) ;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/tesla_data/parameters.js:
--------------------------------------------------------------------------------
1 | //APIurl = "YOUR_API_URL" // hardcode the API url
2 |
3 | //show_battery_percentage = true; // show the battery percentage above the battery bar
4 | //show_range = true; // show the estimated range above the battery bar
5 | //show_range_est = true; // show range estimated instead of the car's range estimate
6 | //show_data_age = false; // show how stale the data is
7 | //custom_theme = ""; // if you want to load a theme (some available themes are "3d")
8 |
9 | //debug_data = ""; // this will force the widget to pull data from iCloud json files (put sample JSON in the themes directory)
10 |
11 | //debug_size = "small"; // which size should the widget try to run as when run through Scriptable. (small, medium, large)
--------------------------------------------------------------------------------