evccg is a Garmin wearable app that displays real-time data from evcc, an open-source platform for solar-optimized EV charging.
You can find the app in the Garmin Connect IQ store:
https://apps.garmin.com/apps/2bc2ba9d-b117-4cdf-8fa7-078c1ac90ab0
The user manual is published via GitHub Pages at:
https://evccg.the-ninth.com
This README covers the following topics:
Built using the Garmin Connect IQ SDK, evccg includes the following application types:
- Glance: A quick overview of site statistics, available in both full-featured and minimal ("tiny") versions for lower-memory devices.
- Widget: The main interface, including detail views for multiple sites.
- Background: Supports HTTP requests for glance functionality on devices with limited memory.
Further reading:
- evccg User Manual
- evccg User Manual - Glance
- evccg User Manual - Widget
- Connect IQ for Developers
- Connect IQ SDK
The project is organized into the following directories:
The root directory contains essential project files.
Key files:
README.md: This filemanifest.xml: Defines the app's structure, supported devices, and required permissions (e.g., storage, background tasks)monkey.jungle: The build script that determines available features per device. It includes extensive documentation in the file itself.
Further reading:
- evccg User Manual - Supported Devices: outlines the capabilities of each device
- Connect IQ SDK Core Topics - Manifest and Permissions
- Connect IQ SDK Core Topics - Build Configuration
Contains VS Code customizations.
Key files:
tasks.json: defines custom build tasks.- evccg: Generate Source for Tiny Glance - see further below for details
- evccg: Generate Icons for All Devices - see further below for details
- evccg: Copy drawables.xml for All Devices - see further below for details
- evccg: Generate Icons for epix2pro47mm - see further below for details
Contains the user manual, published at https://evccg.the-ninth.com.
Key files:
README.md: The user manual itself_config.yml: Theme configurationassets/css/style.css: Custom styles to adapt the theme
This folder contains the SVG icon source files and scripts used to generate device-specific PNG icons.
Icons are created in multiple font sizes based on each device's display resolution and are stored in the corresponding resource folders.
At runtime, the app dynamically selects the appropriate font size based on the displayed content.
Key files:
generate.json: Defines font/icon sizes per device which icons to generate.drawables*.xml: Garmin resource definition file that associates icon files with resource identifiers used in the source code. Three versions of this file exist, and one is copied—along with the corresponding generated PNGs—into each device-specific resource folder based on the device type.generate.bat: Generates icons.generate.js: JavaScript script, run bygenerate.batusing Windows Scripting Host
For more information on these files, see To Generate the Device-Specific Icons.
In the Connect IQ SDK, resources define:
- Properties: Parameters stored outside the app, hidden to the user
- Settings: User-facing configurations
- Drawables: Image assets used by the app
- Strings: Text values like app name and version
Folder breakdown:
/resources: Shared across all devices/resources-drawables/[devicename]: Drawables specific to individual devices. However, if multiple devices share the same font sizes, they can also share drawables. In such cases, only one folder is created for the shared drawables, typically named after one of the devices. The other devices then reference this folder inmonkey.jungle. Similarly, ingenerate.json, there will be a single entry for the shared drawable set, using thedevicesproperty to list all applicable devices./resources-drawables/[devicename]: Properties specific to individual devices. Optional and currently only used for a few devices./resources-settings/site1: Settings for devices supporting one site/resources-settings/site5: Settings for devices supporting up to five sites
Further reading:
The app is written in Monkey C, Garmin's programming language, using the Connect IQ SDK API for UI, settings, persistent storage, and HTTP requests to evcc.
Annotations:
(:glance)and(:background)are used to isolate code for those specific modules.- Extensive use of exclude annotations helps the build system tailor the code to each device (see the root folder for details).
Key files and directories:
/source/app/EvccApp.mc: Entry point for glance, widget, and background modes/source/_base: Shared code/source/background: Background data handling, to support the tiny glance/glance: Glance versions (full-featured and tiny)/widget: Widget app/source-annot-glance: Some classes are required in the glance scope for the full-featured glance but not for the tiny glance. Therefore, their source files must be duplicated—once with the:glanceannotation and once without. Thesource-annot-glancedirectory contains the master versions of these annotated files, and any modifications to these classes should be made there./source-annot-tinyglance: This folder contains the duplicated source files mentioned above, with the:glanceannotation removed./source-annot-tinyglance/create-source-files.bat: This script generates the duplicated source files (see here for details).
Further reading:
Follow the steps below to build, run, and test the app using the Connect IQ SDK and Garmin simulator.
-
Install:
- Visual Studio Code
- Git
- Connect IQ SDK
- Monkey C extension for VS Code
-
Open VS Code and clone the
evcc-garminrepository -
Open any file in the
/sourcefolder -
Press F5 to start the simulator and select a target device
-
Go to
File→Edit Persistent Storage→Edit Application.Propertiesand configure as needed- Use
https://demo.evcc.io/for testing if you don’t have a local instance - To allow HTTP URLs, uncheck
Settings > Use Device HTTPS Requirements
- Use
- Press
CTRL+SHIFT+P→Monkey C: Build Current Project
The following command generates the .iq file, which is used for uploading the app to the Garmin Connect IQ Store.
- Make sure all debug statements are commented out. See Removing Debug Statements for details.
- Press
CTRL+SHIFT+P→Monkey C: Export Project
As explained in Folders /source, the /source-annot-tinyglance folder contains duplicates of the files in /source-annot-glance, but without the :glance annotations. All changes should be made only in /source-annot-glance.
After making changes, run /source-annot-tinyglance/create-source-files.bat to regenerate the tiny glance source files. This script copies the files and removes the :glance annotations. It requires sed for Windows to be installed and added to your PATH environment variable. You can download it from here.
Alternatively, you can use the custom VS Code task defined in the project. Press CTRL+SHIFT+B and choose evccg: Generate Source for Tiny Glance to run the batch file from the integrated terminal.
To support a new device:
-
If the device isn't available in your current SDK, launch the SDK Manager and download/activate the latest version.
-
In
manifest.xml, check the new device in the supported device list. -
Configure device-specific features in the
monkey.junglebuild file (see Root Folder/). You need to at least add an entry for theresourcePath. ForsourcePathandexcludeAnnotations, the default is a good starting point. You can launch the app in the simulator to evaluate whether any adjustments are needed. For example:- If the app reports that vector fonts are not supported, switch to static fonts—or to static optimized fonts if standard sizes overlap.
- If out-of-memory errors occur during testing, consider switching to the tiny glance, limiting support to a single site, and removing the system info view.
- If watchdog errors occur (indicating that execution is taking too long), switch from complex to simple calculations.
- If the select/enter button is not in the standard 30° position, switch to the appropriate option.
-
Generate the icons for the new device following the steps described in How to Generate Icons for a New Device.
-
Test in the simulator (see above)
-
Export the project (
CTRL+SHIFT+P→Monkey C: Export Project) and upload the.iqfile to the Connect IQ Store
All icons are stored in SVG format in the icons folder. From these, device-specific PNGs are generated at multiple font sizes, tailored to each device's display resolution. The resulting PNGs are stored in the appropriate resource folders.
At runtime, the app dynamically selects the appropriate icon size based on the displayed content. Font sizes per device are defined in /icons/generate.json.
Each icon also requires entries in /icons/drawables.xml for every size it will be used at.
The following sections explain how font sizes are selected, how to add support for a new device, how to add new icons, and how to generate the PNGs.
For glances, a single font size is defined in generate.json under each device entry:
icon_glance→ always equalingFONT_GLANCEas defined by Garmin for the device
For the widget, five icon/font sizes are defined per device in generate.json:
icon_mediumicon_smallicon_tinyicon_xtinyicon_micro
Note: These entries do not set the font sizes themselves. Instead, they must match the font sizes the app selects at runtime, based on one of the three methods below:
Modern devices support scalable vector fonts, allowing the app to evenly distribute font sizes as needed.
- The app calculates
icon_mediumbased on the standardFONT_MEDIUMand screen resolution. icon_microis derived fromFONT_XTINYand, if necessary, adjusted to maintain a proportional relationship toFONT_MEDIUM.- The remaining font sizes (
small,tiny,xtiny) are evenly distributed betweenmediumandmicro.
You can enable debugging in EvccUILibWidgetSingleton to print the actual font sizes used at runtime.
In static mode, the app uses the device’s built-in font sizes without modification. You can refer to Garmin’s Device Reference for exact font dimensions per device.
The mapping is as follows:
icon_medium→FONT_MEDIUMicon_small→FONT_SMALLicon_tiny→FONT_TINYicon_xtiny→FONT_GLANCEicon_micro→FONT_XTINY
In this mode, the app still relies on the device's standard fonts, but improves distribution by filtering out duplicate sizes, resulting in a more balanced range.
You can enable debugging in EvccUILibWidgetSingleton to print the actual font sizes used at runtime.
Example: If
FONT_SMALLandFONT_TINYare the same size, the app might assign:
icon_medium→FONT_MEDIUMicon_small→FONT_SMALLicon_tiny→FONT_GLANCEicon_xtiny→FONT_XTINYicon_micro→FONT_XTINY
To determine the actual font sizes used by the app, follow these steps:
-
Add an entry to
generate.jsonfor the target device. You can use placeholder values for the icon sizes—copying from a similar existing device works fine. This step is only required to get the app running so you can retrieve the font sizes. -
Generate the icons by running:
generate.bat [device-family]
Replace
[device-family]with the name of the entry you just added togenerate.json. -
Ensure you added the device-specific
resourcePathinmonkey.jungle, with the device-specific drawable path (see above). -
Run the app in the simulator, open the widget, and press the
mkey twice to open the system info view. The app will print the actual font sizes to the debug console. -
Update the
generate.jsonentry with the correct font sizes based on the output. -
Re-generate the icons with the updated sizes:
generate.bat [device-family]
Example entries:
"fenix6":{
"fontMode":"static",
"deviceType":"noglance-lowmemory",
"logo_flash":"40",
"logo_evcc":"13",
"icon_micro":"19",
"icon_xtiny":"22",
"icon_tiny":"29",
"icon_small":"32",
"icon_medium":"37"
},
"fenix847mm": {
"fontMode": "vector",
"logo_flash": "65",
"logo_evcc": "26",
"icon_glance": "42",
"icon_micro": "33",
"icon_xtiny": "40",
"icon_tiny": "46",
"icon_small": "53",
"icon_medium": "59"
}Explanation of fields:
icon_*: These values correspond to the font sizes selected by the app, based on the method described above.logo_flash: Must match the Launcher Icon Size as listed in Garmin’s Device Reference.logo_evcc: The logo shown at the bottom of the screen. Typically set to 65% oficon_xtiny.deviceType: Enables special handling for older devices that either do not support glances or use the tiny glance. Can be omitted for newer models. See the section ondrawables*.xmlfor more details.fontMode: A comment indicating the font sizing mode used by the app for this device (e.g.,"vector","static", or"static-optimized").devices: A comment listing the devices this entry applies to.
To add, remove, or change icons, you'll need to update the following files in the /icons directory:
This file serves as input for the PNG generation script.
-
The
device-familiesentry, covered in the previous section, defines available icon sizes for each device family. -
The
filessection specifies how each SVG should be processed and which sizes to generate. Each entry includes:anti-aliasing: Level of anti-aliasing applied by Inkscape (range:0= none,3= max).types: An array of size identifiers (e.g.,icon_medium) that match entries indevice-families. PNGs will be generated for each type listed.png-name(optional): For entries with only onetype, this overrides the default PNG filename.
Example:
"files": { "battery_empty.svg": { "anti-aliasing": "3", "types": ["icon_glance", "icon_xtiny", "icon_tiny", "icon_small", "icon_medium"] }, "sun.svg": { "anti-aliasing": "3", "types": ["icon_xtiny", "icon_tiny", "icon_small", "icon_medium"] }, "evcc.svg": { "anti-aliasing": "3", "types": ["logo_evcc"], "png-name": "logo_evcc.png" } }
In this example:
battery_empty.svgwill be generated in multiple sizes for various UI contexts.sun.svgis limited to widget-specific sizes.evcc.svgis generated in a single size with a custom filename.
Default PNG naming convention:
<type>_<name>.png
Where:
<type>= icon size (e.g.,icon_medium)<name>= original SVG filename (without extension)
For example, the output PNGs for sun.svg would include:
icon_xtiny_sun.png, icon_small_sun.png, etc.
Defines resources for use in the app via the Connect IQ SDK.
There are three versions of this file:
drawables.xml: The default version, containing all icons and using the full color palette available on the device.drawables-noglance-lowmemory.xml: A version for devices without glances and with limited memory. Glance icons are omitted, and all other icons are compiled with a reduced color palette and no transparency to conserve memory.drawables-tinyglance.xml: A version for tiny glance devices. Only the icons used in the tiny glance are included, with a reduced color palette and no transparency.
Each icon must have an entry for every size it's used in, and in all applicable versions of the drawables file.
For example, the medium-sized sun.svg icon would be defined in both drawables.xml and drawables-tinyglance.xml like this:
<bitmap scope="foreground" id="sun_medium" filename="icon_medium_sun_crushed.png" packingFormat="png"/>scope="foreground"indicates the icon is only available in widget contexts.
In drawables-noglance-lowmemory.xml, the same icon would appear as:
<bitmap scope="foreground" id="sun_medium" filename="icon_medium_sun.png">
<palette disableTransparency="true">
<color>FFFFFF</color>
<color>AAAAAA</color>
<color>555555</color>
<color>000000</color>
</palette>
</bitmap>- The
<palette>tag limits the icon to four grayscale colors: white, light gray, dark gray, and black. disableTransparency="true"disables transparency, which would otherwise occupy a separate color slot. In this case, transparency is replaced with black—already part of the palette—so no extra color is needed.
Further reading:
- See the Connect IQ SDK Resources documentation for more information on resource definitions.
- The Connect IQ FAQ explains how to optimize bitmaps by reducing the color palette and removing transparency.
This file contains Monkey C classes that define resource sets used in the app. Each resource set defines font sizes to be used and maps them to the corresponding PNG resources.
EvccWidgetResourceSetBase: Defines resources for widgetsEvccGlanceResourceSetBase: Defines resources for glances
These mappings act as the bridge between the resource definitions in drawables.xml and the font sizes used in the Monkey C code.
Whenever you make changes to /icons/generate.json, any of the /icons/drawables*.xml, or any of the SVG files, you need to run generate.bat to regenerate the device-specific PNG icons and copy drawables.xml into each device’s resource folder.
Based on the deviceType specified in generate.json, the script selects the appropriate drawables*.xml version and generates certain icons without transparency.
You can run generate.bat with the following parameters:
- No parameters: Generates icons for all devices.
- Device folder (e.g.
resources-fenix7): Generates icons only for that specific device. drawables.xml: Copiesdrawables.xmlto all device resource folders without generating icons.
Alternatively, you can use the custom VS Code task defined in the project. Press CTRL+SHIFT+B and choose one of the following tasks to run the batch file from the integrated terminal.
- evccg: Generate Icons for All Devices: Generates icons for all devices.
- evccg: Copy drawables.xml for All Devices: Copies
drawables.xmlto all device resource folders without generating icons. - evccg: Generate Icons for <device name>: Generates icons only for that specific device. Note: not available for all devices.
Dependencies
The script relies on the following third-party tools:
- Inkscape – Converts SVG files to PNG. It must be available in your system’s
PATH. - pngcrush.exe – Optimizes PNG files. This tool is included in the project directory and requires no installation.
To conserve memory, short codes are used for exception messages that result from programming errors (as opposed to user-related issues such as misconfiguration).
| Shortcode | Class | Description |
|---|---|---|
| CENTANGINV | EvccPageIndicator | setCenterAngle: is not a valid value |
| DOTANGINV | EvccPageIndicator | setDotDistanceAngle: is not a valid value |
| FFNTFND | EvccResourceSets | Font faces not found |
| JUSTCENTONL | EvccHorizontalBlock | Vertical block supports only justify center |
| JUSTNOTSUP | EvccHorizontalBlock | Horizontal block does not support justification for elements |
| MTHDUN | EvccPreRenderContentTask | Unknown method |
| NODC | EvccBlock | :dc not set |
| NOFONT | EvccBlock | :font not set |
| NOICFOR | EvccIconBlock | Icon not found for font |
| NOREZID | EvccBitmapBlock | ResourceId is missing |
| ORBITDEG | EvccPageIndicator | orbitXY: is not a valid value |
| VECNOTSUP | EvccResourceSets | Device does not support vector fonts |
A table listing supported devices and their features is available in the user manual.
Below is an additional reference for developers, showing the Connect IQ (CIQ) API level supported by each device.
| Device | CIQ API Level |
|---|---|
| fenix6 | 3.4.0 |
| fenix6s | 3.4.0 |
| fenix6pro | 3.4.0 |
| fenix6spro | 3.4.0 |
| fenix6xpro | 3.4.0 |
| fenix7 | 5.1.0 |
| fenix7s | 5.1.0 |
| fenix7x | 5.1.0 |
| epix2pro42mm | 5.1.0 |
| epix2pro47mm | 5.1.0 |
| epix2pro51mm | 5.1.0 |
| fenix7pro | 5.1.0 |
| fenix7pronowifi | 5.1.0 |
| fenix7spro | 5.1.0 |
| fenix7xpro | 5.1.0 |
| fenix7xpronowifi | 5.1.0 |
| fenix843mm | 5.1.0 |
| fenix847mm | 5.1.0 |
| fenix8solar47mm | 5.1.0 |
| fenix8solar51mm | 5.1.0 |
| fr745 | 3.3.0 |
| fr945 | 3.3.0 |
| fr945lte | 3.4.0 |
| fr955 | 5.1.0 |
| fr165 | 5.1.0 |
| fr165m | 5.1.0 |
| fr265 | 5.1.0 |
| fr265s | 5.1.0 |
| fr965 | 5.1.0 |
| venu2 | 5.0.0 |
| venu2plus | 5.0.0 |
| venu2s | 5.0.0 |
| venu3 | 5.1.0 |
| venu3s | 5.1.0 |
| vivoactive3 | 3.1.0 |
| vivoactive3m | 3.2.0 |
| vivoactive3mlte | 3.1.0 |
| vivoactive4 | 3.3.0 |
| vivoactive4s | 3.3.0 |
| vivoactive5 | 5.1.0 |
| vivoactive6 | 5.1.0 |
Further reading
A collection of useful information for working on this project.
While debug statements are only printed in debug builds, they still occupy code space in release builds. Therefore, when building a release, all debug statements should be commented out.
To find all active debug statements in VS Code, press CTRL+SHIFT+H to open the global search and replace panel. Enable regular expressions by clicking the .* icon next to the search field, and use the following pattern to locate all active debug statements:
(?<!\/\/ )EvccHelperBase\.debug\(
To deactivate the debug statements, replace them with:
// EvccHelperBase.debug(
This will comment them out without affecting any lines that are already commented.