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.metiq.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.
- Widget: The main interface, including detail views for multiple sites.
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 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.metiq.com.
Key files:
README.md: The user manual itself_config.yml: Theme configurationassets/css/style.css: Custom styles to adapt the theme
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/drawables/generated/[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./resources/drawables/src: The SVG (vector) graphics used to generate the drawables, along with the XML resource definitions. Both are consumed by the script that generates the device-specific drawable folders./resources/settings: App settings visible to the user/resources/strings: Shared across all devices
Further reading:
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.
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)is used to isolate code used in the memory-constrained glance.- 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/main: Main source codeapp/EvccApp.mc: Entry point for glance and widget modesdata/: Data layer, including evcc state representation, web request handling, storage, as well as access to app configuration and string resourcesshared/: Shared components such as constants, exceptions, and helper functionsui/: UI implementation for widget and glance
-
/source/properties: Device-specific constantsbase/DeviceProperties.mc: Singleton providing property access with default valuesbase/devices/[devicename]: Optional overrides for device-specific properties
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
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 the select/enter button is not in the standard 30° position, switch to the appropriate option.
- Set the appropriate exclude annotation for a round or rectangular screen.
-
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 /scripts/generate-drawables/generate.json.
Each icon also requires entries in /resources/drawables/src/xml/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:
"venu2":{
"fontMode":"static-opt",
"logo_flash":"70",
"logo_evcc":"22",
"icon_medium":"58",
"icon_small":"49",
"icon_tiny":"43",
"icon_xtiny":"32",
"icon_micro":"32",
"icon_glance":"43"
},
"fenix847mm": {
"fontMode": "vector",
"logo_flash": "65",
"logo_evcc": "26",
"icon_medium": "59",
"icon_small": "53",
"icon_tiny": "46",
"icon_xtiny": "40",
"icon_micro": "33",
"icon_glance": "42"
}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.fontMode: A comment indicating the font sizing mode used by the app for this device (e.g.,"vector","static", or"static-optimized").
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.
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.
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 |
|---|---|
| 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 |
| fenix8pro47mm | 5.1.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 |
| fr970 | 5.1.0 |
| venu2 | 5.0.0 |
| venu2plus | 5.0.0 |
| venu2s | 5.0.0 |
| venu3 | 5.1.0 |
| venu3s | 5.1.0 |
| venux1 | 5.1.0 |
| venu441mm | 5.1.0 |
| venu447mm | 5.1.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:
(?<!\/\/ )Logger\.debug\(
To deactivate the debug statements, replace them with:
// Logger.debug(
This will comment them out without affecting any lines that are already commented.