diff --git a/packages/eez-studio-types/index.d.ts b/packages/eez-studio-types/index.d.ts index 056fc1114..40a659652 100644 --- a/packages/eez-studio-types/index.d.ts +++ b/packages/eez-studio-types/index.d.ts @@ -312,6 +312,11 @@ export interface IActionComponentDefinition { migrateProperties?: (component: IActionComponent) => void; execute?: (context: IDashboardComponentContext) => void; + + // If true, the build generates an extern C prototype and a registerComponent() + // call. The user provides the implementation in their firmware project. + // Generated function: void eez_flow_ext_(FlowState*, unsigned) + isNative?: boolean; } interface IMessageFromWorker { @@ -932,11 +937,35 @@ export interface IDashboardComponentContext { throwError: (errorMessage: string) => void; } +export interface IStructureField { + name: string; + type: ValueType; +} + +export interface IStructureDefinition { + name: string; + fields: IStructureField[]; +} + +export interface IEnumMember { + name: string; + value: number; +} + +export interface IEnumDefinition { + name: string; + members: IEnumMember[]; +} + //////////////////////////////////////////////////////////////////////////////// export interface IEezFlowEditor { registerActionComponent(definition: IActionComponentDefinition): void; + registerStructureVariableType(structure: IStructureDefinition): void; + + registerEnumVariableType(enumDef: IEnumDefinition): void; + registerObjectVariableType( name: string, objectVariableType: IObjectVariableType diff --git a/packages/project-editor/build/assets.ts b/packages/project-editor/build/assets.ts index 677ffe0f4..0ed8b92b9 100644 --- a/packages/project-editor/build/assets.ts +++ b/packages/project-editor/build/assets.ts @@ -177,6 +177,8 @@ export class Assets { [componentType: number]: string; } = {}; + nativeExtensionComponents: { componentType: number; className: string }[] = []; + isUsingCrypyoSha256: boolean = false; lvglBuild: LVGLBuild; @@ -1808,6 +1810,14 @@ export async function buildAssets( await assets.lvglBuild.buildActionsDecl(); } + if ( + !sectionNames || + sectionNames.indexOf("LVGL_EXT_COMPONENT_DECL") !== -1 + ) { + result.LVGL_EXT_COMPONENT_DECL = + await assets.lvglBuild.buildExtComponentDecl(); + } + if ( !sectionNames || sectionNames.indexOf("LVGL_ACTIONS_ARRAY_DEF") !== -1 @@ -1873,7 +1883,7 @@ export async function buildAssets( // build eez-gui-lite source code if (sectionNames!.indexOf("EEZ_GUI_LITE_DECL") !== -1 || sectionNames!.indexOf("EEZ_GUI_LITE_DEF") !== -1) { - const buildEezGuiLite = new BuildEezGuiLite(assets); + const buildEezGuiLite = new BuildEezGuiLite(assets); if (sectionNames!.indexOf("EEZ_GUI_LITE_DECL") !== -1) { result.EEZ_GUI_LITE_DECL = buildEezGuiLite.buildDecl(); } diff --git a/packages/project-editor/build/flows.ts b/packages/project-editor/build/flows.ts index 5263ef830..819d04c7c 100644 --- a/packages/project-editor/build/flows.ts +++ b/packages/project-editor/build/flows.ts @@ -118,6 +118,19 @@ function getComponentIdOfComponent(assets: Assets, component: Component) { assets.dashboardComponentClassNameToComponentIdMap[name] = flowComponentId; assets.dashboardComponentTypeToNameMap[flowComponentId] = name; + + if ( + classInfo.isNative && + assets.projectStore.projectTypeTraits.isLVGL && + !assets.nativeExtensionComponents.find( + c => c.componentType === flowComponentId + ) + ) { + assets.nativeExtensionComponents.push({ + componentType: flowComponentId!, + className: name + }); + } } } else { console.error("UNEXPECTED!"); @@ -755,9 +768,15 @@ export function buildFlowStructs(assets: Assets) { const defs = []; + // Combine project-defined and imported (extension) structures + const allStructures = [ + ...assets.projectStore.project.variables.structures, + ...assets.projectStore.importedStructureVariableTypes.values() + ]; + // enum FlowStructures const structureEnumItems = []; - for (const structure of assets.projectStore.project.variables.structures) { + for (const structure of allStructures) { structureEnumItems.push( `${TAB}${getName( "FLOW_STRUCTURE_", @@ -777,7 +796,7 @@ export function buildFlowStructs(assets: Assets) { // enum FlowArrayOfStructures const arrayOfStructureEnumItems = []; - for (const structure of assets.projectStore.project.variables.structures) { + for (const structure of allStructures) { arrayOfStructureEnumItems.push( `${TAB}${getName( "FLOW_ARRAY_OF_STRUCTURE_", @@ -796,7 +815,7 @@ export function buildFlowStructs(assets: Assets) { ); } - for (const structure of assets.projectStore.project.variables.structures) { + for (const structure of allStructures) { const fieldEnumItems = []; for (const field of structure.fields) { fieldEnumItems.push( @@ -1030,8 +1049,14 @@ export function buildFlowStructValues(assets: Assets) { ); } - for (const structure of assets.projectStore.project.variables.structures) { - buildStructure(structure); + // Include both project-defined and imported (extension) structures + const allStructuresForValues = [ + ...assets.projectStore.project.variables.structures, + ...assets.projectStore.importedStructureVariableTypes.values() + ]; + + for (const structure of allStructuresForValues) { + buildStructure(structure as Structure); } return build.result; diff --git a/packages/project-editor/core/object.ts b/packages/project-editor/core/object.ts index f85ece885..7fc4c2df6 100644 --- a/packages/project-editor/core/object.ts +++ b/packages/project-editor/core/object.ts @@ -470,6 +470,8 @@ export interface ClassInfo { execute?: (context: IDashboardComponentContext) => void; + isNative?: boolean; + findChildIndex?: (parent: IEezObject[], child: IEezObject) => number; widgetEvents?: WidgetEvents | ((object: IEezObject) => WidgetEvents); diff --git a/packages/project-editor/features/variable/value-type.tsx b/packages/project-editor/features/variable/value-type.tsx index 45340df76..da76c9074 100644 --- a/packages/project-editor/features/variable/value-type.tsx +++ b/packages/project-editor/features/variable/value-type.tsx @@ -413,7 +413,7 @@ export function registerSystemEnum({ const existingSystemEnum = SystemEnum.SYSTEM_ENUMS.find( systemEnum => systemEnum.compareTo(name, projectTypes, lvglVersions) ); - + if (existingSystemEnum) { existingSystemEnum.members = members; existingSystemEnum._membersMap = undefined; @@ -682,9 +682,13 @@ export const VariableTypeSelect = observer( ) : []; + const isLVGL = this.props.project.projectTypeTraits.isLVGL; const enumTypes = [ ...project.variables.enums, - ...getSystemEnums(this.props.project._store) + ...getSystemEnums(this.props.project._store), + ...[...project._store.importedEnumVariableTypes.values()].filter( + e => !isLVGL || e.name.includes("/") + ) ]; const enums = enumTypes.map(enumDef => ( @@ -702,9 +706,9 @@ export const VariableTypeSelect = observer( const structureTypes = [ ...project.variables.structures, - ...(this.props.project.projectTypeTraits.isLVGL - ? [] - : SYSTEM_STRUCTURES) + ...(isLVGL ? [] : SYSTEM_STRUCTURES), + ...[...project._store.importedStructureVariableTypes.values()].filter( + s => !isLVGL || s.name.includes("/")) ]; const structures = this.props.project.projectTypeTraits diff --git a/packages/project-editor/features/variable/variable.tsx b/packages/project-editor/features/variable/variable.tsx index 8b3b54f46..489317fb5 100644 --- a/packages/project-editor/features/variable/variable.tsx +++ b/packages/project-editor/features/variable/variable.tsx @@ -1737,6 +1737,11 @@ export class ProjectVariables extends EezObject { for (const enumDef of systemEnums) { map.set(enumDef.name, enumDef); } + for (const [name, enumDef] of projectStore.importedEnumVariableTypes) { + if (!map.has(name)) { + map.set(name, enumDef); + } + } return map; } @@ -1748,6 +1753,12 @@ export class ProjectVariables extends EezObject { for (const structure of SYSTEM_STRUCTURES) { map.set(structure.name, structure); } + const projectStore = ProjectEditor.getProjectStore(this); + for (const [name, structure] of projectStore.importedStructureVariableTypes) { + if (!map.has(name)) { + map.set(name, structure); + } + } return map; } } diff --git a/packages/project-editor/flow/component.tsx b/packages/project-editor/flow/component.tsx index 7a2b8e70e..a0111836a 100644 --- a/packages/project-editor/flow/component.tsx +++ b/packages/project-editor/flow/component.tsx @@ -4680,7 +4680,8 @@ export function createActionComponentClass( componentHeaderColor: actionComponentDefinition.componentHeaderColor, componentPaletteGroupName, - execute: actionComponentDefinition.execute + execute: actionComponentDefinition.execute, + isNative: actionComponentDefinition.isNative }); override makeEditable() { diff --git a/packages/project-editor/flow/components/components-registry.ts b/packages/project-editor/flow/components/components-registry.ts index dfdd71b9f..fa78a8551 100644 --- a/packages/project-editor/flow/components/components-registry.ts +++ b/packages/project-editor/flow/components/components-registry.ts @@ -42,7 +42,10 @@ export function getAllComponentClasses( isProperSubclassOf( objectClassInfo.objectClass.classInfo, ProjectEditor.WidgetClass.classInfo - )) + )) || + // Extension components only for LVGL Project (registered via public API) have "/" in their name + (projectStore.projectTypeTraits.isLVGL && + objectClassInfo.name.includes("/")) ); } diff --git a/packages/project-editor/lvgl/build.ts b/packages/project-editor/lvgl/build.ts index f42131d42..1290ec553 100644 --- a/packages/project-editor/lvgl/build.ts +++ b/packages/project-editor/lvgl/build.ts @@ -68,6 +68,12 @@ interface UpdateColorCallbackForUserWidget { updateColorsForPage: UpdateColorCallbackForPage; } +// Converts an extension component class nameto a valid C identifier +function extComponentFunctionName(className: string): string { + const sanitized = className.replace(/[^a-zA-Z0-9]/g, "_"); + return `eez_flow_ext_${sanitized}`; +} + export class LVGLBuild extends Build { project: Project; @@ -2119,6 +2125,20 @@ export class LVGLBuild extends Build { build.blockStart("void create_screens() {"); + if ( + this.assets.projectStore.projectTypeTraits.hasFlowSupport && + this.assets.nativeExtensionComponents.length > 0 + ) { + build.line("// Register native extension components"); + for (const ext of this.assets.nativeExtensionComponents) { + const fnName = extComponentFunctionName(ext.className); + build.line( + `eez_flow_register_ext_component(${ext.componentType}, ${fnName});` + ); + } + build.line(""); + } + if ( this.assets.projectStore.projectTypeTraits.hasFlowSupport && this.styles.length > 0 @@ -2678,6 +2698,24 @@ extern ext_font_desc_t fonts[]; return this.result; } + async buildExtComponentDecl() { + if (!this.project.projectTypeTraits.hasFlowSupport) { + return ""; + } + + this.startBuild(); + const build = this; + + for (const ext of this.assets.nativeExtensionComponents) { + const fnName = extComponentFunctionName(ext.className); + build.line( + `extern void ${fnName}(void *flowState, unsigned componentIndex);` + ); + } + + return this.result; + } + async buildActionsArrayDef() { if (!this.project.projectTypeTraits.hasFlowSupport) { return ""; diff --git a/packages/project-editor/store/index.ts b/packages/project-editor/store/index.ts index cce17b33a..85e019047 100644 --- a/packages/project-editor/store/index.ts +++ b/packages/project-editor/store/index.ts @@ -31,16 +31,19 @@ import { } from "project-editor/core/object"; import { CurrentSearch, startNewSearch } from "project-editor/core/search"; -import type { DataContext } from "project-editor/features/variable/variable"; +import type { + DataContext, + IStructure, + IStructureField, + IEnum, + IEnumMember +} from "project-editor/features/variable/variable"; import type { RuntimeBase } from "project-editor/flow/runtime/runtime"; import { ProjectEditor } from "project-editor/project-editor-interface"; -import type { - ExtensionDirective, - Project -} from "project-editor/project/project"; +import type {Project} from "project-editor/project/project"; import { findPropertyByNameInObject, @@ -139,6 +142,16 @@ interface ExtensionContent { name: string; type: IObjectVariableType; }[]; + + structureVariableTypes: { + name: string; + type: IStructure; + }[]; + + enumsVariableTypes: { + name: string; + type: IEnum; + }[]; } type ProjectStoreContext = @@ -200,6 +213,8 @@ export class ProjectStore { extensionNames: string[]; objectVariableTypes = new Map(); importedActionComponentClasses = new Map(); + importedStructureVariableTypes = new Map(); + importedEnumVariableTypes = new Map(); objectCollapsedStore = observable.box< { object: IEezObject; collapsed: Set }[] @@ -1259,7 +1274,7 @@ export class ProjectStore { // Also exit full simulator mode if active if (this.layoutModels.isDockerSimulatorMode) { this.onExitFullSimulatorMode(); - } + } } async setEditorMode(force: boolean = false) { @@ -1415,84 +1430,144 @@ export class ProjectStore { buildImportedExtensions(project: Project) { // build importedExtensionToExtensionContent - const importedExtensionToExtensionContent = new Map< - ExtensionDirective, - ExtensionContent - >(); - - const extensionDirectives = project.settings?.general?.extensions; - if (extensionDirectives) { - for (const extensionDirective of extensionDirectives) { - if (extensionDirective.extensionName) { - const extension = extensions.get( - extensionDirective.extensionName - ); + const seenExtensionNames = new Set(); + const extensionNamesToProcess: string[] = []; - if (!extension) { - continue; + const collectFrom = (p: Project) => { + const exts = p.settings?.general?.extensions; + if (exts) { + for (const ext of exts) { + if ( + ext.extensionName && + !seenExtensionNames.has(ext.extensionName) + ) { + seenExtensionNames.add(ext.extensionName); + extensionNamesToProcess.push(ext.extensionName); } + } + } + }; - if (!extension.eezFlowExtensionInit) { - continue; - } + collectFrom(project); + for (const openProj of this.openProjectsManager.openProjects) { + collectFrom(openProj.project); + } + + // build extensionContentByName + const extensionContentByName = new Map(); + + for (const extensionName of extensionNamesToProcess) { + const extension = extensions.get(extensionName); + + if (!extension) { + continue; + } + + if (!extension.eezFlowExtensionInit) { + continue; + } + + try { + const extensionContent: ExtensionContent = { + extensionName: extension.name, + actionComponentClasses: [], + objectVariableTypes: [], + structureVariableTypes: [], + enumsVariableTypes: [] + }; + + extension.eezFlowExtensionInit({ + registerActionComponent: ( + actionComponentDefinition: IActionComponentDefinition + ) => { + const { className, actionComponentClass } = + ProjectEditor.createActionComponentClass( + actionComponentDefinition, + `${extension.name}/${actionComponentDefinition.name}` + ); + + if (!className || !actionComponentClass) { + throw new Error( + `Failed to create action component class for "${extension.name}/${actionComponentDefinition.name}"` + ); + } - try { - const extensionContent: ExtensionContent = { - extensionName: extension.name, - actionComponentClasses: [], - objectVariableTypes: [] - }; - - extension.eezFlowExtensionInit({ - registerActionComponent: ( - actionComponentDefinition: IActionComponentDefinition - ) => { - const { className, actionComponentClass } = - ProjectEditor.createActionComponentClass( - actionComponentDefinition, - `${extension.name}/${actionComponentDefinition.name}` - ); - - if (!className || !actionComponentClass) { - throw new Error( - `Failed to create action component class for "${extension.name}/${actionComponentDefinition.name}"` - ); + extensionContent.actionComponentClasses.push({ + className, + actionComponentClass + }); + }, + + registerObjectVariableType: ( + name: string, + objectVariableType: IObjectVariableType + ) => { + extensionContent.objectVariableTypes.push({ + name: `${extension.name}/${name}`, + type: createObjectVariableType( + objectVariableType + ) + }); + }, + + registerStructureVariableType: (structure: { + name: string; + fields: { name: string; type: string }[]; + }) => { + const fullName = `${extension.name}/${structure.name}`; + const fields = structure.fields as IStructureField[]; + extensionContent.structureVariableTypes.push({ + name: fullName, + type: { + name: fullName, + fields, + get fieldsMap() { + const map = new Map< + string, + IStructureField + >(); + for (const f of fields) { + map.set(f.name, f); + } + return map; } + } + }); + }, - extensionContent.actionComponentClasses.push({ - className, - actionComponentClass - }); - }, - - registerObjectVariableType: ( - name: string, - objectVariableType: IObjectVariableType - ) => { - extensionContent.objectVariableTypes.push({ - name: `${extension.name}/${name}`, - type: createObjectVariableType( - objectVariableType - ) - }); - }, - - showGenericDialog, - - validators: { - required: validators.required, - rangeInclusive: validators.rangeInclusive + registerEnumVariableType: (enumDef: { + name: string; + members: { name: string; value: number }[]; + }) => { + const fullName = `${extension.name}/${enumDef.name}`; + const members = enumDef.members as IEnumMember[]; + extensionContent.enumsVariableTypes.push({ + name: fullName, + type: { + name: fullName, + members, + get membersMap() { + const map = new Map(); + for (const m of members) { + map.set(m.name, m); + } + return map; + } } }); + }, - importedExtensionToExtensionContent.set( - extensionDirective, - extensionContent - ); - } catch (err) { - console.error(err); + showGenericDialog, + + validators: { + required: validators.required, + rangeInclusive: validators.rangeInclusive } - } + }); + + extensionContentByName.set(extensionName, extensionContent); + } catch (err) { + console.error(err); } } @@ -1509,7 +1584,7 @@ export class ProjectStore { } // insert object variable types from imported extensions - for (const extensionContent of importedExtensionToExtensionContent.values()) { + for (const extensionContent of extensionContentByName.values()) { for (const objectVariableType of extensionContent.objectVariableTypes) { this.objectVariableTypes.set( objectVariableType.name, @@ -1527,7 +1602,7 @@ export class ProjectStore { >(); // insert action component classes from imported extensions - for (const extensionContent of importedExtensionToExtensionContent.values()) { + for (const extensionContent of extensionContentByName.values()) { for (const actionComponentClass of extensionContent.actionComponentClasses) { this.importedActionComponentClasses.set( actionComponentClass.className, @@ -1535,8 +1610,34 @@ export class ProjectStore { ); } } + + // + // build importedStructureVariableTypes + // + this.importedStructureVariableTypes = new Map(); + + for (const extensionContent of extensionContentByName.values()) { + for (const structure of extensionContent.structureVariableTypes) { + this.importedStructureVariableTypes.set( + structure.name, + structure.type + ); + } + } + + // + // build importedEnumVariableTypes + // + this.importedEnumVariableTypes = new Map(); + + for (const extensionContent of extensionContentByName.values()) { + for (const enumDef of extensionContent.enumsVariableTypes) { + this.importedEnumVariableTypes.set(enumDef.name, enumDef.type); + } + } } + getClassByName(className: string) { return this.importedActionComponentClasses.get(className); } diff --git a/packages/project-editor/store/open-projects-manager.ts b/packages/project-editor/store/open-projects-manager.ts index 91604a476..96eaf5cd1 100644 --- a/packages/project-editor/store/open-projects-manager.ts +++ b/packages/project-editor/store/open-projects-manager.ts @@ -196,6 +196,8 @@ export class OpenProjectsManager { this.openProjects = [...map.values()]; }); + this.projectStore.buildImportedExtensions(project); + //this._dumpOpenProjects(); return project; diff --git a/resources/eez-framework-amalgamation/eez-flow.cpp b/resources/eez-framework-amalgamation/eez-flow.cpp index de350fe96..b4f21cde4 100644 --- a/resources/eez-framework-amalgamation/eez-flow.cpp +++ b/resources/eez-framework-amalgamation/eez-flow.cpp @@ -25,7 +25,7 @@ namespace eez { void executeActionFunction(int actionId) { eez::flow::executeLvglActionHook(actionId - 1); } -} +} // ----------------------------------------------------------------------------- // core/alloc.cpp // ----------------------------------------------------------------------------- @@ -81,7 +81,7 @@ void getAllocInfo(uint32_t &free, uint32_t &alloc) { alloc = mon.total_size - mon.free_size - g_allocMemoryAtStart; #endif } -} +} // ----------------------------------------------------------------------------- // core/assets.cpp // ----------------------------------------------------------------------------- @@ -217,7 +217,7 @@ const uint16_t *getThemeColors(int themeIndex) { const uint16_t *getColors() { return static_cast(g_mainAssets->colorsDefinition->colors.items); } -} +} // ----------------------------------------------------------------------------- // core/debug.cpp // ----------------------------------------------------------------------------- @@ -243,12 +243,12 @@ void Trace(TraceType traceType, const char *format, ...) { pushErrorTraceHook(buffer, strlen(buffer)); } } -} -} +} +} extern "C" void debug_trace(const char *str, size_t len) { eez::debug::pushDebugTraceHook(str, len); } -#endif +#endif // ----------------------------------------------------------------------------- // core/memory.cpp // ----------------------------------------------------------------------------- @@ -276,7 +276,7 @@ uint8_t *allocBuffer(uint32_t size) { return (uint8_t *)lv_mem_alloc(size); #endif } -} +} // ----------------------------------------------------------------------------- // core/os.cpp // ----------------------------------------------------------------------------- @@ -291,122 +291,122 @@ uint32_t millis() { return lv_tick_get(); #endif } -} +} // ----------------------------------------------------------------------------- // core/unit.cpp // ----------------------------------------------------------------------------- #include namespace eez { const char *g_unitNames[] = { - "", - "V", - "mV", - "A", - "mA", - "uA", - "W", - "mW", - "s", - "ms", - DEGREE_SYMBOL"C", - "rpm", - "\xb4", - "K\xb4", - "M\xb4", - "%", - "Hz", - "mHz", - "KHz", - "MHz", - "J", - "F", - "mF", - "uF", - "nF", - "pF", - "minutes", - "VA", - "VAR", - DEGREE_SYMBOL, - "Vpp", - "mVpp", - "App", - "mApp", - "uApp", + "", + "V", + "mV", + "A", + "mA", + "uA", + "W", + "mW", + "s", + "ms", + DEGREE_SYMBOL"C", + "rpm", + "\xb4", + "K\xb4", + "M\xb4", + "%", + "Hz", + "mHz", + "KHz", + "MHz", + "J", + "F", + "mF", + "uF", + "nF", + "pF", + "minutes", + "VA", + "VAR", + DEGREE_SYMBOL, + "Vpp", + "mVpp", + "App", + "mApp", + "uApp", }; const Unit g_baseUnit[] = { - UNIT_NONE, - UNIT_VOLT, - UNIT_VOLT, - UNIT_AMPER, - UNIT_AMPER, - UNIT_AMPER, - UNIT_WATT, - UNIT_WATT, - UNIT_SECOND, - UNIT_SECOND, - UNIT_CELSIUS, - UNIT_RPM, - UNIT_OHM, - UNIT_OHM, - UNIT_OHM, - UNIT_PERCENT, - UNIT_HERTZ, - UNIT_HERTZ, - UNIT_HERTZ, - UNIT_HERTZ, - UNIT_JOULE, - UNIT_FARAD, - UNIT_FARAD, - UNIT_FARAD, - UNIT_FARAD, - UNIT_FARAD, - UNIT_SECOND, - UNIT_VOLT_AMPERE, - UNIT_VOLT_AMPERE, - UNIT_DEGREE, - UNIT_VOLT_PP, - UNIT_VOLT_PP, - UNIT_AMPER_PP, - UNIT_AMPER_PP, - UNIT_AMPER_PP, + UNIT_NONE, + UNIT_VOLT, + UNIT_VOLT, + UNIT_AMPER, + UNIT_AMPER, + UNIT_AMPER, + UNIT_WATT, + UNIT_WATT, + UNIT_SECOND, + UNIT_SECOND, + UNIT_CELSIUS, + UNIT_RPM, + UNIT_OHM, + UNIT_OHM, + UNIT_OHM, + UNIT_PERCENT, + UNIT_HERTZ, + UNIT_HERTZ, + UNIT_HERTZ, + UNIT_HERTZ, + UNIT_JOULE, + UNIT_FARAD, + UNIT_FARAD, + UNIT_FARAD, + UNIT_FARAD, + UNIT_FARAD, + UNIT_SECOND, + UNIT_VOLT_AMPERE, + UNIT_VOLT_AMPERE, + UNIT_DEGREE, + UNIT_VOLT_PP, + UNIT_VOLT_PP, + UNIT_AMPER_PP, + UNIT_AMPER_PP, + UNIT_AMPER_PP, }; const float g_unitFactor[] = { - 1.0f, - 1.0f, - 1E-3f, - 1.0f, - 1E-3f, - 1E-6f, - 1.0f, - 1E-3f, - 1.0f, - 1E-3f, - 1.0f, - 1.0f, - 1.0f, - 1E3f, - 1E6f, - 1.0f, - 1.0f, - 1E-3f, - 1E3f, - 1E6f, - 1.0f, - 1.0f, - 1E-3f, - 1E-6f, - 1E-9f, - 1E-12f, - 60.0f, - 1.0f, - 1.0f, - 1.0f, - 1.0f, - 1E-3f, - 1.0f, - 1E-3f, - 1E-6f, + 1.0f, + 1.0f, + 1E-3f, + 1.0f, + 1E-3f, + 1E-6f, + 1.0f, + 1E-3f, + 1.0f, + 1E-3f, + 1.0f, + 1.0f, + 1.0f, + 1E3f, + 1E6f, + 1.0f, + 1.0f, + 1E-3f, + 1E3f, + 1E6f, + 1.0f, + 1.0f, + 1E-3f, + 1E-6f, + 1E-9f, + 1E-12f, + 60.0f, + 1.0f, + 1.0f, + 1.0f, + 1.0f, + 1E-3f, + 1.0f, + 1E-3f, + 1E-6f, }; Unit getUnitFromName(const char *unitName) { if (unitName) { @@ -510,7 +510,7 @@ Unit getSmallestUnit(Unit unit, float min, float precision) { } return UNIT_UNKNOWN; } -} +} // ----------------------------------------------------------------------------- // core/util.cpp // ----------------------------------------------------------------------------- @@ -661,9 +661,9 @@ void stringAppendLoad(char *str, size_t maxStrLength, float value) { uint32_t crc32(const uint8_t *mem_block, size_t block_size) { uint32_t crc = 0xFFFFFFFF; for (size_t i = 0; i < block_size; ++i) { - uint32_t byte = mem_block[i]; + uint32_t byte = mem_block[i]; crc = crc ^ byte; - for (int j = 0; j < 8; ++j) { + for (int j = 0; j < 8; ++j) { uint32_t mask = -((int32_t)crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } @@ -1056,7 +1056,7 @@ void getBaseFileName(const char *path, char *baseName, unsigned baseNameSize) { } baseName[n] = 0; } -} +} #if defined(M_PI) static const float PI_FLOAT = (float)M_PI; #else @@ -1234,7 +1234,7 @@ EasingFuncType g_easingFuncs[] = { eez_easeOutBounce, eez_easeInOutBounce, }; -} +} // ----------------------------------------------------------------------------- // core/value.cpp // ----------------------------------------------------------------------------- @@ -1385,7 +1385,7 @@ static void FLOAT_value_to_text(const Value &value, char *text, int count) { floatValue /= getUnitFactor(unit); } } else { - floatValue = 0; + floatValue = 0; } if (!isNaN(floatValue)) { if ((value.getOptions() & FLOAT_OPTIONS_LESS_THEN) != 0) { @@ -1464,7 +1464,7 @@ static void DOUBLE_value_to_text(const Value &value, char *text, int count) { doubleValue /= getUnitFactor(unit); } } else { - doubleValue = 0; + doubleValue = 0; } if (!isNaN(doubleValue)) { if ((value.getOptions() & FLOAT_OPTIONS_LESS_THEN) != 0) { @@ -1685,7 +1685,7 @@ static const char *DATE_value_type_name(const Value &value) { return "date"; } static bool compare_VERSIONED_STRING_value(const Value &a, const Value &b) { - return a.type == b.type && a.unit == b.unit; + return a.type == b.type && a.unit == b.unit; } static void VERSIONED_STRING_value_to_text(const Value &value, char *text, int count) { const char *str = value.getString(); @@ -1913,7 +1913,7 @@ Value MakeEnumDefinitionValue(uint8_t enumValue, uint8_t enumDefinition) { return value; } const char *Value::getString() const { - auto value = getValue(); + auto value = getValue(); if (value.type == VALUE_TYPE_STRING_REF) { return ((StringRef *)value.refValue)->str; } @@ -2508,7 +2508,7 @@ void setVar(int16_t id, const Value& value) { set(value.getString()); } } -} +} // ----------------------------------------------------------------------------- // flow/components.cpp // ----------------------------------------------------------------------------- @@ -2572,44 +2572,59 @@ static ExecuteComponentFunctionType g_executeComponentFunctions[] = { executeDelayComponent, executeErrorComponent, executeCatchErrorComponent, - executeCounterComponent, + executeCounterComponent, executeLoopComponent, executeShowPageComponent, - nullptr, + nullptr, nullptr, nullptr, nullptr, - executeNoopComponent, - nullptr, - executeSelectLanguageComponent, + executeNoopComponent, + nullptr, + executeSelectLanguageComponent, nullptr, - executeAnimateComponent, - executeOnEventComponent, - executeLVGLComponent, + executeAnimateComponent, + executeOnEventComponent, + executeLVGLComponent, nullptr, - executeSortArrayComponent, - executeLVGLUserWidgetComponent, - executeTestAndSetComponent, - executeMQTTInitComponent, - executeMQTTConnectComponent, - executeMQTTDisconnectComponent, - executeMQTTEventComponent, - executeMQTTSubscribeComponent, - executeMQTTUnsubscribeComponent, - executeMQTTPublishComponent, - executeLabelInComponent, - executeLabelOutComponent, - executeLVGLApiComponent, - executeSetColorThemeComponent, + executeSortArrayComponent, + executeLVGLUserWidgetComponent, + executeTestAndSetComponent, + executeMQTTInitComponent, + executeMQTTConnectComponent, + executeMQTTDisconnectComponent, + executeMQTTEventComponent, + executeMQTTSubscribeComponent, + executeMQTTUnsubscribeComponent, + executeMQTTPublishComponent, + executeLabelInComponent, + executeLabelOutComponent, + executeLVGLApiComponent, + executeSetColorThemeComponent, }; + +#define MAX_EXT_COMPONENTS 64 +static struct { uint16_t type; ExecuteComponentFunctionType fn; } + g_extComponents[MAX_EXT_COMPONENTS]; +static uint8_t g_numExtComponents = 0; + void registerComponent(ComponentTypes componentType, ExecuteComponentFunctionType executeComponentFunction) { - if (componentType >= defs_v3::COMPONENT_TYPE_START_ACTION) { + if (componentType >= defs_v3::FIRST_DASHBOARD_ACTION_COMPONENT_TYPE) { + if (g_numExtComponents < MAX_EXT_COMPONENTS) { + g_extComponents[g_numExtComponents++] = { + (uint16_t)componentType, executeComponentFunction + }; + } + } else if (componentType >= defs_v3::COMPONENT_TYPE_START_ACTION) { g_executeComponentFunctions[componentType - defs_v3::COMPONENT_TYPE_START_ACTION] = executeComponentFunction; } } bool hasExecFunc(FlowState *flowState, unsigned componentIndex) { auto component = flowState->flow->components[componentIndex]; if (component->type >= defs_v3::FIRST_DASHBOARD_ACTION_COMPONENT_TYPE) { + for (uint8_t i = 0; i < g_numExtComponents; i++) { + if (g_extComponents[i].type == component->type) return true; + } return false; } else if (component->type >= defs_v3::COMPONENT_TYPE_START_ACTION) { auto executeComponentFunction = g_executeComponentFunctions[component->type - defs_v3::COMPONENT_TYPE_START_ACTION]; @@ -2620,6 +2635,15 @@ bool hasExecFunc(FlowState *flowState, unsigned componentIndex) { void executeComponent(FlowState *flowState, unsigned componentIndex) { auto component = flowState->flow->components[componentIndex]; if (component->type >= defs_v3::FIRST_DASHBOARD_ACTION_COMPONENT_TYPE) { + for (uint8_t i = 0; i < g_numExtComponents; i++) { + if (g_extComponents[i].type == component->type) { + g_extComponents[i].fn(flowState, componentIndex); + return; + } + } + char errorMessage[100]; + snprintf(errorMessage, sizeof(errorMessage), "Unknown ext component type=%d\n", component->type); + throwError(flowState, componentIndex, errorMessage); return; } else if (component->type >= defs_v3::COMPONENT_TYPE_START_ACTION) { auto executeComponentFunction = g_executeComponentFunctions[component->type - defs_v3::COMPONENT_TYPE_START_ACTION]; @@ -2632,8 +2656,8 @@ void executeComponent(FlowState *flowState, unsigned componentIndex) { snprintf(errorMessage, sizeof(errorMessage), "Unknown component at index = %d, type = %d\n", componentIndex, component->type); throwError(flowState, componentIndex, errorMessage); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/animate.cpp // ----------------------------------------------------------------------------- @@ -2706,8 +2730,8 @@ void executeAnimateComponent(FlowState *flowState, unsigned componentIndex) { } } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/call_action.cpp // ----------------------------------------------------------------------------- @@ -2764,8 +2788,8 @@ void executeCallActionComponent(FlowState *flowState, unsigned componentIndex) { } executeCallAction(flowState, componentIndex, flowIndex, Value()); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/catch_error.cpp // ----------------------------------------------------------------------------- @@ -2777,8 +2801,8 @@ void executeCatchErrorComponent(FlowState *flowState, unsigned componentIndex) { deallocateComponentExecutionState(flowState, componentIndex); propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/compare.cpp // ----------------------------------------------------------------------------- @@ -2807,8 +2831,8 @@ void executeCompareComponent(FlowState *flowState, unsigned componentIndex) { } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/constant.cpp // ----------------------------------------------------------------------------- @@ -2823,8 +2847,8 @@ void executeConstantComponent(FlowState *flowState, unsigned componentIndex) { propagateValue(flowState, componentIndex, 1, sourceValue); propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/counter.cpp // ----------------------------------------------------------------------------- @@ -2851,8 +2875,8 @@ void executeCounterComponent(FlowState *flowState, unsigned componentIndex) { propagateValue(flowState, componentIndex, 1); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/delay.cpp // ----------------------------------------------------------------------------- @@ -2890,8 +2914,8 @@ void executeDelayComponent(FlowState *flowState, unsigned componentIndex) { } } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/end.cpp // ----------------------------------------------------------------------------- @@ -2907,8 +2931,8 @@ void executeEndComponent(FlowState *flowState, unsigned componentIndex) { stopScriptHook(); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/error.cpp // ----------------------------------------------------------------------------- @@ -2921,8 +2945,8 @@ void executeErrorComponent(FlowState *flowState, unsigned componentIndex) { } throwError(flowState, componentIndex, FlowError::Plain(expressionValue.getString())); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/expr_eval.cpp // ----------------------------------------------------------------------------- @@ -2936,8 +2960,8 @@ void executeEvalExprComponent(FlowState *flowState, unsigned componentIndex) { propagateValue(flowState, componentIndex, 1, expressionValue); propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/input.cpp // ----------------------------------------------------------------------------- @@ -2991,8 +3015,8 @@ void executeInputComponent(FlowState *flowState, unsigned componentIndex) { inputActionComponentExecutionState->value = value; } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/is_true.cpp // ----------------------------------------------------------------------------- @@ -3017,8 +3041,8 @@ void executeIsTrueComponent(FlowState *flowState, unsigned componentIndex) { } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/label_in.cpp // ----------------------------------------------------------------------------- @@ -3028,8 +3052,8 @@ void executeLabelInComponent(FlowState *flowState, unsigned componentIndex) { EEZ_UNUSED(flowState); EEZ_UNUSED(componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/label_out.cpp // ----------------------------------------------------------------------------- @@ -3044,8 +3068,8 @@ void executeLabelOutComponent(FlowState *flowState, unsigned componentIndex) { propagateValueThroughSeqout(flowState, component->labelInComponentIndex); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/line_chart_widget.cpp // ----------------------------------------------------------------------------- @@ -3066,8 +3090,8 @@ void executeLogComponent(FlowState *flowState, unsigned componentIndex) { } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/loop.cpp // ----------------------------------------------------------------------------- @@ -3143,8 +3167,8 @@ void executeLoopComponent(FlowState *flowState, unsigned componentIndex) { propagateValueThroughSeqout(flowState, componentIndex); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/lvgl.cpp // ----------------------------------------------------------------------------- @@ -3774,9 +3798,9 @@ ACTION_START(objStyleSetProperty) lv_obj_set_local_style_prop(obj, (lv_style_prop_t)property, style_value, part | state); } else { throwError(flowState, componentIndex, FlowError::NotFoundInAction("Font", str, "objStyleSetProperty", actionIndex)); - } + } } else if ( -#if LVGL_VERSION_MAJOR >= 9 +#if LVGL_VERSION_MAJOR >= 9 property == LV_STYLE_BG_IMAGE_SRC || property == LV_STYLE_ARC_IMAGE_SRC #else @@ -3794,11 +3818,11 @@ ACTION_START(objStyleSetProperty) lv_obj_set_local_style_prop(obj, (lv_style_prop_t)property, style_value, part | state); } else { throwError(flowState, componentIndex, FlowError::NotFoundInAction("Font", str, "objStyleSetProperty", actionIndex)); - } + } } else if ( property == LV_STYLE_BG_COLOR || property == LV_STYLE_BG_GRAD_COLOR || -#if LVGL_VERSION_MAJOR >= 9 +#if LVGL_VERSION_MAJOR >= 9 property == LV_STYLE_BG_IMAGE_RECOLOR || #else property == LV_STYLE_BG_IMG_RECOLOR || @@ -4250,8 +4274,8 @@ void executeLVGLApiComponent(FlowState *flowState, unsigned componentIndex) { } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/lvgl_user_widget.cpp // ----------------------------------------------------------------------------- @@ -4315,8 +4339,8 @@ void executeLVGLUserWidgetComponent(FlowState *flowState, unsigned componentInde } } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/mqtt.cpp // ----------------------------------------------------------------------------- @@ -4724,8 +4748,8 @@ void executeMQTTPublishComponent(FlowState *flowState, unsigned componentIndex) } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} #ifndef EEZ_MQTT_ADAPTER int eez_mqtt_init(const char *protocol, const char *host, int port, const char *username, const char *password, void **handle) { EEZ_UNUSED(protocol); @@ -4773,8 +4797,8 @@ namespace flow { void executeNoopComponent(FlowState *flowState, unsigned componentIndex) { propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/on_event.cpp // ----------------------------------------------------------------------------- @@ -4784,8 +4808,8 @@ void executeOnEventComponent(FlowState *flowState, unsigned componentIndex) { propagateValue(flowState, componentIndex, 1, flowState->eventValue); propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/output.cpp // ----------------------------------------------------------------------------- @@ -4818,8 +4842,8 @@ void executeOutputComponent(FlowState *flowState, unsigned componentIndex) { } propagateValue(flowState->parentFlowState, flowState->parentComponentIndex, parentComponentOutputIndex, value); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/select_language.cpp // ----------------------------------------------------------------------------- @@ -4845,8 +4869,8 @@ void executeSelectLanguageComponent(FlowState *flowState, unsigned componentInde snprintf(message, sizeof(message), "Unknown language %s", language); throwError(flowState, componentIndex, FlowError::Plain(message)); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/set_color_theme.cpp // ----------------------------------------------------------------------------- @@ -4862,8 +4886,8 @@ void executeSetColorThemeComponent(FlowState *flowState, unsigned componentIndex const char *theme = themeValue.getString(); lvglSetColorThemeHook(theme); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/set_variable.cpp // ----------------------------------------------------------------------------- @@ -4886,8 +4910,8 @@ void executeSetVariableComponent(FlowState *flowState, unsigned componentIndex) } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/show_page.cpp // ----------------------------------------------------------------------------- @@ -4901,8 +4925,8 @@ void executeShowPageComponent(FlowState *flowState, unsigned componentIndex) { replacePageHook(component->page, 0, 0, 0); propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/sort_array.cpp // ----------------------------------------------------------------------------- @@ -4990,8 +5014,8 @@ void executeSortArrayComponent(FlowState *flowState, unsigned componentIndex) { sortArray(component, array); propagateValue(flowState, componentIndex, component->outputs.count - 1, arrayValue); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/start.cpp // ----------------------------------------------------------------------------- @@ -5000,8 +5024,8 @@ namespace flow { void executeStartComponent(FlowState *flowState, unsigned componentIndex) { propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/switch.cpp // ----------------------------------------------------------------------------- @@ -5033,8 +5057,8 @@ void executeSwitchComponent(FlowState *flowState, unsigned componentIndex) { } propagateValueThroughSeqout(flowState, componentIndex); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/test_and_set.cpp // ----------------------------------------------------------------------------- @@ -5056,8 +5080,8 @@ void executeTestAndSetComponent(FlowState *flowState, unsigned componentIndex) { addToQueue(flowState, componentIndex, -1, -1, -1, true); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/components/watch_variable.cpp // ----------------------------------------------------------------------------- @@ -5086,8 +5110,8 @@ void executeWatchVariableComponent(FlowState *flowState, unsigned componentIndex } } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/date.cpp // ----------------------------------------------------------------------------- @@ -5114,9 +5138,9 @@ static struct { TimeChangeRule dstStart; TimeChangeRule dstEnd; } g_dstRules[] = { - { { Last, Sun, Mar, 2 }, { Last, Sun, Oct, 3 } }, - { { Second, Sun, Mar, 2 }, { First, Sun, Nov, 2 } }, - { { First, Sun, Oct, 2 }, { First, Sun, Apr, 3 } }, + { { Last, Sun, Mar, 2 }, { Last, Sun, Oct, 3 } }, + { { Second, Sun, Mar, 2 }, { First, Sun, Nov, 2 } }, + { { First, Sun, Oct, 2 }, { First, Sun, Apr, 3 } }, }; Format g_localeFormat = FORMAT_DMY_24; int g_timeZone = 0; @@ -5160,14 +5184,14 @@ Date makeDate(int year, int month, int day, int hours, int minutes, int seconds, Date time = year * 365 * SECONDS_PER_DAY; for (int i = 0; i < year; i++) { if (LEAP_YEAR(i)) { - time += SECONDS_PER_DAY; + time += SECONDS_PER_DAY; } } for (int i = 1; i < month; i++) { if ((i == 2) && LEAP_YEAR(year)) { time += SECONDS_PER_DAY * 29; } else { - time += SECONDS_PER_DAY * monthDays[i - 1]; + time += SECONDS_PER_DAY * monthDays[i - 1]; } } time += (day - 1) * SECONDS_PER_DAY; @@ -5183,26 +5207,26 @@ void breakDate(Date time, int &result_year, int &result_month, int &result_day, uint8_t month, monthLength; uint32_t days; result_milliseconds = time % 1000; - time /= 1000; + time /= 1000; result_seconds = time % 60; - time /= 60; + time /= 60; result_minutes = time % 60; - time /= 60; + time /= 60; result_hours = time % 24; - time /= 24; + time /= 24; year = 0; days = 0; while ((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { year++; } - result_year = year + 1970; + result_year = year + 1970; days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; + time -= days; days = 0; month = 0; monthLength = 0; for (month = 0; month < 12; ++month) { - if (month == 1) { + if (month == 1) { if (LEAP_YEAR(year)) { monthLength = 29; } else { @@ -5217,8 +5241,8 @@ void breakDate(Date time, int &result_year, int &result_month, int &result_day, break; } } - result_month = month + 1; - result_day = time + 1; + result_month = month + 1; + result_day = time + 1; } int getYear(Date time) { int year, month, day, hours, minutes, seconds, milliseconds; @@ -5303,24 +5327,24 @@ static uint8_t dayOfWeek(int y, int m, int d) { static Date timeChangeRuleToLocal(TimeChangeRule &r, int year) { uint8_t month = r.month; uint8_t week = r.week; - if (week == 0) { - if (++month > 12) { + if (week == 0) { + if (++month > 12) { month = 1; ++year; } - week = 1; + week = 1; } Date time = makeDate(year, month, 1, r.hours, 0, 0, 0); uint8_t dow = dayOfWeek(year, month, 1); time += (7 * (week - 1) + (r.dow - dow + 7) % 7) * SECONDS_PER_DAY; if (r.week == 0) { - time -= 7 * SECONDS_PER_DAY; + time -= 7 * SECONDS_PER_DAY; } return time; } -} -} -} +} +} +} // ----------------------------------------------------------------------------- // flow/debugger.cpp // ----------------------------------------------------------------------------- @@ -5332,31 +5356,31 @@ namespace eez { namespace flow { #define MAX_ARRAY_SIZE_TRANSFERRED_IN_DEBUGGER 1000 enum MessagesToDebugger { - MESSAGE_TO_DEBUGGER_STATE_CHANGED, - MESSAGE_TO_DEBUGGER_ADD_TO_QUEUE, - MESSAGE_TO_DEBUGGER_REMOVE_FROM_QUEUE, - MESSAGE_TO_DEBUGGER_GLOBAL_VARIABLE_INIT, - MESSAGE_TO_DEBUGGER_LOCAL_VARIABLE_INIT, - MESSAGE_TO_DEBUGGER_COMPONENT_INPUT_INIT, - MESSAGE_TO_DEBUGGER_VALUE_CHANGED, - MESSAGE_TO_DEBUGGER_FLOW_STATE_CREATED, - MESSAGE_TO_DEBUGGER_FLOW_STATE_TIMELINE_CHANGED, - MESSAGE_TO_DEBUGGER_FLOW_STATE_DESTROYED, - MESSAGE_TO_DEBUGGER_FLOW_STATE_ERROR, - MESSAGE_TO_DEBUGGER_LOG, - MESSAGE_TO_DEBUGGER_PAGE_CHANGED, - MESSAGE_TO_DEBUGGER_COMPONENT_EXECUTION_STATE_CHANGED, - MESSAGE_TO_DEBUGGER_COMPONENT_ASYNC_STATE_CHANGED + MESSAGE_TO_DEBUGGER_STATE_CHANGED, + MESSAGE_TO_DEBUGGER_ADD_TO_QUEUE, + MESSAGE_TO_DEBUGGER_REMOVE_FROM_QUEUE, + MESSAGE_TO_DEBUGGER_GLOBAL_VARIABLE_INIT, + MESSAGE_TO_DEBUGGER_LOCAL_VARIABLE_INIT, + MESSAGE_TO_DEBUGGER_COMPONENT_INPUT_INIT, + MESSAGE_TO_DEBUGGER_VALUE_CHANGED, + MESSAGE_TO_DEBUGGER_FLOW_STATE_CREATED, + MESSAGE_TO_DEBUGGER_FLOW_STATE_TIMELINE_CHANGED, + MESSAGE_TO_DEBUGGER_FLOW_STATE_DESTROYED, + MESSAGE_TO_DEBUGGER_FLOW_STATE_ERROR, + MESSAGE_TO_DEBUGGER_LOG, + MESSAGE_TO_DEBUGGER_PAGE_CHANGED, + MESSAGE_TO_DEBUGGER_COMPONENT_EXECUTION_STATE_CHANGED, + MESSAGE_TO_DEBUGGER_COMPONENT_ASYNC_STATE_CHANGED }; enum MessagesFromDebugger { - MESSAGE_FROM_DEBUGGER_RESUME, - MESSAGE_FROM_DEBUGGER_PAUSE, - MESSAGE_FROM_DEBUGGER_SINGLE_STEP, - MESSAGE_FROM_DEBUGGER_ADD_BREAKPOINT, - MESSAGE_FROM_DEBUGGER_REMOVE_BREAKPOINT, - MESSAGE_FROM_DEBUGGER_ENABLE_BREAKPOINT, - MESSAGE_FROM_DEBUGGER_DISABLE_BREAKPOINT, - MESSAGE_FROM_DEBUGGER_MODE + MESSAGE_FROM_DEBUGGER_RESUME, + MESSAGE_FROM_DEBUGGER_PAUSE, + MESSAGE_FROM_DEBUGGER_SINGLE_STEP, + MESSAGE_FROM_DEBUGGER_ADD_BREAKPOINT, + MESSAGE_FROM_DEBUGGER_REMOVE_BREAKPOINT, + MESSAGE_FROM_DEBUGGER_ENABLE_BREAKPOINT, + MESSAGE_FROM_DEBUGGER_DISABLE_BREAKPOINT, + MESSAGE_FROM_DEBUGGER_MODE }; enum LogItemType { LOG_ITEM_TYPE_FATAL, @@ -5962,8 +5986,8 @@ void onPageChanged(int previousPageId, int activePageId, bool activePageIsFromSt writeDebuggerBufferHook(buffer, strlen(buffer)); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/expression.cpp // ----------------------------------------------------------------------------- @@ -6159,8 +6183,8 @@ bool evalAssignableProperty(FlowState *flowState, int componentIndex, int proper } return evalAssignableExpression(flowState, componentIndex, component->properties[propertyIndex]->evalInstructions, result, errorMessage, numInstructionBytes, iterators); } -} -} +} +} // ----------------------------------------------------------------------------- // flow/flow.cpp // ----------------------------------------------------------------------------- @@ -6391,8 +6415,8 @@ void onArrayValueFree(ArrayValue *arrayValue) { onFreeMQTTConnection(arrayValue); } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/hooks.cpp // ----------------------------------------------------------------------------- @@ -6525,8 +6549,8 @@ double (*getDateNowHook)() = getDateNowDefaultImplementation; double (*getDateNowHook)() = nullptr; #endif void (*onFlowErrorHook)(FlowState *flowState, int componentIndex, const char *errorMessage) = nullptr; -} -} +} +} // ----------------------------------------------------------------------------- // flow/lvgl_api.cpp // ----------------------------------------------------------------------------- @@ -6799,6 +6823,12 @@ void replacePageHook(int16_t pageId, uint32_t animType, uint32_t speed, uint32_t extern "C" void flowOnPageLoaded(unsigned pageIndex) { eez::flow::getPageFlowState(eez::g_mainAssets, pageIndex); } +extern "C" void eez_flow_register_ext_component(unsigned componentType, void (*fn)(void *flowState, unsigned componentIndex)) { + eez::flow::registerComponent( + (eez::flow::defs_v3::ComponentTypes)componentType, + (eez::flow::ExecuteComponentFunctionType)fn + ); +} extern "C" void flowPropagateValue(void *flowState, unsigned componentIndex, unsigned outputIndex) { eez::flow::propagateValue((eez::flow::FlowState *)flowState, componentIndex, outputIndex); } @@ -6992,9 +7022,9 @@ extern "C" int compareRollerOptions(lv_roller_t *roller, const char *new_val, co } } #if LVGL_VERSION_MAJOR >= 9 - return lv_roller_get_option_count((const lv_obj_t *)roller) == new_option_count ? 0 : 1; + return lv_roller_get_option_count((const lv_obj_t *)roller) == new_option_count ? 0 : 1; #else - return lv_roller_get_option_cnt((const lv_obj_t *)roller) == new_option_count ? 0 : 1; + return lv_roller_get_option_cnt((const lv_obj_t *)roller) == new_option_count ? 0 : 1; #endif } uint32_t eez_flow_get_selected_theme_index() { @@ -8945,7 +8975,7 @@ static void do_OPERATION_TYPE_LVGL_COLOR_DARKEN(EvalStack &stack) { Value level = stack.pop().getValue(); if (!color.isInt32OrLess() || !level.isInt32OrLess()) { stack.push(Value::makeError()); - return; + return; } auto adjustedColor = lv_color_darken(lv_color_hex(color.getUInt32()), (uint8_t)level.getUInt32()); #if LVGL_VERSION_MAJOR >= 9 @@ -8960,7 +8990,7 @@ static void do_OPERATION_TYPE_LVGL_COLOR_LIGHTEN(EvalStack &stack) { Value level = stack.pop().getValue(); if (!color.isInt32OrLess() || !level.isInt32OrLess()) { stack.push(Value::makeError()); - return; + return; } auto adjustedColor = lv_color_lighten(lv_color_hex(color.getUInt32()), (uint8_t)level.getUInt32()); #if LVGL_VERSION_MAJOR >= 9 @@ -9184,8 +9214,8 @@ EvalOperation g_evalOperations[] = { do_OPERATION_TYPE_LVGL_COLOR_DARKEN, do_OPERATION_TYPE_LVGL_COLOR_LIGHTEN, }; -} -} +} +} // ----------------------------------------------------------------------------- // flow/private.cpp // ----------------------------------------------------------------------------- @@ -9809,8 +9839,8 @@ void throwError(FlowState *flowState, int componentIndex, const FlowError &error void enableThrowError(bool enable) { g_enableThrowError = enable; } -} -} +} +} // ----------------------------------------------------------------------------- // flow/queue.cpp // ----------------------------------------------------------------------------- @@ -9924,8 +9954,8 @@ void removeTasksFromQueueForFlowState(FlowState *flowState) { } } } -} -} +} +} // ----------------------------------------------------------------------------- // flow/watch_list.cpp // ----------------------------------------------------------------------------- @@ -10009,5 +10039,5 @@ void removeWatchesForFlowState(FlowState *flowState) { unsigned getWatchListSize() { return g_watchList.size; } -} -} \ No newline at end of file +} +} diff --git a/resources/eez-framework-amalgamation/eez-flow.h b/resources/eez-framework-amalgamation/eez-flow.h index 3480fbf1a..66be8deeb 100644 --- a/resources/eez-framework-amalgamation/eez-flow.h +++ b/resources/eez-framework-amalgamation/eez-flow.h @@ -2638,6 +2638,7 @@ void eez_flow_delete_screen(int16_t screenId); bool eez_flow_is_screen_created(int16_t screenId); void eez_flow_delete_screen_on_unload(int screenIndex); void flowOnPageLoaded(unsigned pageIndex); +void eez_flow_register_ext_component(unsigned componentType, void (*fn)(void *flowState, unsigned componentIndex)); void *getFlowState(void *flowState, unsigned userWidgetComponentIndexOrPageIndex); void deletePageFlowState(unsigned pageIndex); void flowPropagateValue(void *flowState, unsigned componentIndex, unsigned outputIndex);