Skip to content
This repository has been archived by the owner on Aug 6, 2024. It is now read-only.

Commit

Permalink
Merge pull request #47 from leaphy-robotics/flitz-and-nano-support
Browse files Browse the repository at this point in the history
enhancement: add Flitz and nano support
  • Loading branch information
koen1711 authored Oct 6, 2023
2 parents 52b17f2 + 956bf46 commit 3e440d3
Show file tree
Hide file tree
Showing 12 changed files with 834 additions and 100 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@angular/platform-browser-dynamic": "~15.2.9",
"@angular/router": "~15.2.9",
"@fortawesome/fontawesome-free": "^6.1.1",
"@leaphy-robotics/leaphy-blocks": "1.0.9",
"@leaphy-robotics/leaphy-blocks": "^1.3.5",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@serialport/parser-readline": "^10.3.0",
Expand Down
92 changes: 47 additions & 45 deletions src/app/effects/blockly-editor.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CodeEditorType } from '../domain/code-editor.type';
import {BackendWiredEffects} from "./backend.wired.effects";
import * as Blockly from 'blockly/core';
import Arduino from '@leaphy-robotics/leaphy-blocks/generators/arduino';
import {blocks, blocksJs} from "@leaphy-robotics/leaphy-blocks/blocks/blocks";
import getBlocks from "@leaphy-robotics/leaphy-blocks/blocks/blocks";
import {CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN,
LIST_MODES_MUTATOR_MIXIN,
LIST_MODES_MUTATOR_EXTENSION,
Expand Down Expand Up @@ -47,15 +47,7 @@ export class BlocklyEditorEffects {
private appState: AppState,
private http: HttpClient,
) {
Blockly.registry.register(
Blockly.registry.Type.TOOLBOX_ITEM,
Blockly.ToolboxCategory.registrationName,
LeaphyCategory, true);
Blockly.registry.register(Blockly.registry.Type.TOOLBOX, Blockly.CollapsibleToolboxCategory.registrationName, LeaphyToolbox);
Blockly.defineBlocksWithJsonArray(blocks)
for (const [name, block] of Object.entries(blocksJs)) {
Blockly.Blocks[name] = block;
}



// Variables:
Expand All @@ -72,6 +64,12 @@ export class BlocklyEditorEffects {
'math_change_tooltip',
Extensions.buildTooltipWithFieldText('%{BKY_MATH_CHANGE_TOOLTIP}', 'VAR'));

Blockly.registry.register(
Blockly.registry.Type.TOOLBOX_ITEM,
Blockly.ToolboxCategory.registrationName,
LeaphyCategory, true);
Blockly.registry.register(Blockly.registry.Type.TOOLBOX, Blockly.CollapsibleToolboxCategory.registrationName, LeaphyToolbox);

Extensions.registerMutator(
'math_modes_of_list_mutator', LIST_MODES_MUTATOR_MIXIN,
LIST_MODES_MUTATOR_EXTENSION);
Expand Down Expand Up @@ -118,43 +116,47 @@ export class BlocklyEditorEffects {
this.getXmlContent('./assets/blockly/leaphy-start.xml')
))
.subscribe(([[[element, config], robotType], baseToolboxXml, leaphyToolboxXml, startWorkspaceXml]) => {


const LeaphyTheme = Blockly.Theme.defineTheme('leaphy', {
'blockStyles': defaultBlockStyles,
'categoryStyles': categoryStyles,
'componentStyles': componentStyles,
name: 'leaphy',
})
config.theme = LeaphyTheme;
const parser = new DOMParser();
const toolboxXmlDoc = parser.parseFromString(baseToolboxXml, 'text/xml');
const toolboxElement = toolboxXmlDoc.getElementById('easyBloqsToolbox');
const leaphyCategories = parser.parseFromString(leaphyToolboxXml, 'text/xml');
const leaphyRobotCategory = leaphyCategories.getElementById(robotType.id);
toolboxElement.prepend(leaphyRobotCategory);
if (robotType.showLeaphyExtra) {
const leaphyExtraCategory = leaphyCategories.getElementById(`${robotType.id}_extra`);
toolboxElement.appendChild(leaphyExtraCategory);
}
const serializer = new XMLSerializer();
const toolboxXmlString = serializer.serializeToString(toolboxXmlDoc);
config.toolbox = toolboxXmlString;
// @ts-ignore
const workspace = Blockly.inject(element, config);
const toolbox = workspace.getToolbox();
toolbox.getFlyout().autoClose = false;
const xml = Blockly.utils.xml.textToDom(startWorkspaceXml);
Blockly.Xml.domToWorkspace(xml, workspace);
this.blocklyState.setWorkspace(workspace);
this.blocklyState.setToolboxXml(toolboxXmlString);
if (this.blocklyState.workspaceStatus == WorkspaceStatus.Clean) {
this.backEndWiredEffects.send('restore-workspace-temp', robotType.id);
console.log('Creating new workspace');
const leaphyBlocks = getBlocks(this.appState.getSelectedRobotType().id);
Blockly.defineBlocksWithJsonArray(leaphyBlocks.block)
for (const [name, block] of Object.entries(leaphyBlocks.blockJs)) {
Blockly.Blocks[name] = block;
}
toolbox.selectItemByPosition(0);
toolbox.refreshTheme();
const LeaphyTheme = Blockly.Theme.defineTheme('leaphy', {
'blockStyles': defaultBlockStyles,
'categoryStyles': categoryStyles,
'componentStyles': componentStyles,
name: 'leaphy',
})
config.theme = LeaphyTheme;
const parser = new DOMParser();
const toolboxXmlDoc = parser.parseFromString(baseToolboxXml, 'text/xml');
const toolboxElement = toolboxXmlDoc.getElementById('easyBloqsToolbox');
const leaphyCategories = parser.parseFromString(leaphyToolboxXml, 'text/xml');
const leaphyRobotCategory = leaphyCategories.getElementById(robotType.id);
toolboxElement.prepend(leaphyRobotCategory);
if (robotType.showLeaphyExtra) {
const leaphyExtraCategory = leaphyCategories.getElementById(`${robotType.id}_extra`);
toolboxElement.appendChild(leaphyExtraCategory);
}
const serializer = new XMLSerializer();
const toolboxXmlString = serializer.serializeToString(toolboxXmlDoc);
config.toolbox = toolboxXmlString;
// @ts-ignore
const workspace = Blockly.inject(element, config);
const toolbox = workspace.getToolbox();
toolbox.getFlyout().autoClose = false;
const xml = Blockly.utils.xml.textToDom(startWorkspaceXml);
Blockly.Xml.domToWorkspace(xml, workspace);
this.blocklyState.setWorkspace(workspace);
this.blocklyState.setToolboxXml(toolboxXmlString);
if (this.blocklyState.workspaceStatus == WorkspaceStatus.Clean) {
this.backEndWiredEffects.send('restore-workspace-temp', robotType.id);
}
toolbox.selectItemByPosition(0);
toolbox.refreshTheme();

setTimeout(() => this.blocklyState.setIsSideNavOpen(robotType.showCodeOnStart), 200);
setTimeout(() => this.blocklyState.setIsSideNavOpen(robotType.showCodeOnStart), 200);
});

// When a new project is started, reset the blockly code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ <h3>{{ "SELECT_ROBOT_START_PROJECT" | translate }}</h3>
<div class="col col-md-auto col-sm-6 text-center zoomed" *ngFor="let robot of appState.availableRobotTypes$ | async"
(click)="onRobotSelected(robot)">
<button class="btn shadow-sm btn-primary robot-button"
[ngClass]="{'selected': (appState.selectedRobotType$ | async) === robot}" (click)="onRobotSelected(robot)">
[ngClass]="{'selected': (appState.selectedRobotType$ | async) === robot}">
<img class="imgcenter" src="./assets/{{robot.svgname}}">
</button>
<p class="robot-name">{{robot.name}}</p>
Expand Down
2 changes: 2 additions & 0 deletions src/app/modules/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {VariableDialog} from "./dialogs/variable/variable.dialog";
import {UploadDialog} from "./dialogs/upload/upload.dialog";
import {DebugInformationDialog} from "./dialogs/debug-information/debug-information.dialog";
import {DragDropModule} from "@angular/cdk/drag-drop";
import { SelectRobotTypeDialog } from './dialogs/robot-select/robot-select.dialog';
@NgModule({
declarations: [
ConnectWiredDialog,
Expand All @@ -29,6 +30,7 @@ import {DragDropModule} from "@angular/cdk/drag-drop";
StatusMessageDialog,
CreditsDialog,
LanguageSelectDialog,
SelectRobotTypeDialog,
NameFileDialog,
VariableDialog,
UploadDialog,
Expand Down
15 changes: 15 additions & 0 deletions src/app/modules/core/dialogs/robot-select/robot-select.dialog.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="container">
<img class="leaphyLogo" src="./assets/leaphy-logo-color.svg" />
<div class="robots">
<button mat-stroked-button *ngFor="let robot of data.boardTypes; index as i" (click)="onRobotSelected(robot)">
<div class="robot">
<div style="width: 100%;">
<img src="./assets/{{data.icons[i]}}" width="50" height="50">
</div>
<div class="robot-name">
{{robot}}
</div>
</div>
</button>
</div>
</div>
49 changes: 49 additions & 0 deletions src/app/modules/core/dialogs/robot-select/robot-select.dialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;

.leaphyLogo {
width: 100%;
max-width: 180px;
height: auto;
display: block;
margin: 1em auto;
padding-bottom: 10px;
}

.robots{
display: flex;
flex-direction: column;
width: 200px;
height: fit-content;

button {
margin-bottom: 15px;
}
}
.robot {
//display: flex;
align-items: center;
margin-top: 10px;
margin-bottom: 10px;
height: fit-content;

.robot-name{
width: 100%;
align-content: center;
flex: 1
}
}
}

[mat-stroked-button],
[mat-flat-button] {
color: var(--leaphy-color-primary);
border-color: var(--leaphy-color-secundary);
font-size: 16px;
font-weight: normal;
border-radius: 20px;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';

import { SelectRobotTypeDialog } from './robot-select.dialog';

describe('LanguageSelectComponent', () => {
let component: SelectRobotTypeDialog;
let fixture: ComponentFixture<SelectRobotTypeDialog>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ SelectRobotTypeDialog ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(SelectRobotTypeDialog);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
23 changes: 23 additions & 0 deletions src/app/modules/core/dialogs/robot-select/robot-select.dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { AppState } from 'src/app/state/app.state';
import {MAT_DIALOG_DATA} from '@angular/material/dialog';
import { Inject } from '@angular/core';

@Component({
selector: 'app-robot-select',
templateUrl: './robot-select.dialog.html',
styleUrls: ['./robot-select.dialog.scss']
})
export class SelectRobotTypeDialog {
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<SelectRobotTypeDialog>,
public appState: AppState,

) { }

public onRobotSelected(robotType: String) {
this.dialogRef.close(robotType);
}
}
36 changes: 32 additions & 4 deletions src/app/state/app.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { CodeEditorType } from '../domain/code-editor.type';
import { LocalStorageService } from '../services/localstorage.service';
import { ReloadConfig } from '../domain/reload.config';
import packageJson from '../../../package.json';
import { MatDialog } from '@angular/material/dialog';
import { SelectRobotTypeDialog } from '../modules/core/dialogs/robot-select/robot-select.dialog';

@Injectable({
providedIn: 'root'
Expand All @@ -32,26 +34,36 @@ export class AppState {
['Leaphy Original Extension', 'Leaphy Extra Extension', 'Servo', 'Adafruit GFX Library', 'Adafruit SSD1306', 'Adafruit LSM9DS1 Library', 'Adafruit Unified Sensor']
);

private static leaphyFlitzNanoRobotType = new RobotType('l_flitz_nano', 'Flitz Nano', 'flitz_nano.svg', 'Arduino Nano', 'arduino:avr:nano', 'hex', 'arduino:avr',
['Leaphy Extra Extension', 'Servo', 'Adafruit GFX Library', 'Adafruit SSD1306', 'Adafruit LSM9DS1 Library', 'Adafruit Unified Sensor'], true, false, false
);

private static arduinoNanoRobotType = new RobotType('l_nano', 'Arduino Nano', 'nano.svg', 'Arduino NANO', 'arduino:avr:nano', 'hex', 'arduino:avr',
['Leaphy Original Extension', 'Leaphy Extra Extension', 'Servo', 'Adafruit GFX Library', 'Adafruit SSD1306', 'Adafruit LSM9DS1 Library', 'Adafruit Unified Sensor']
);

public static idToRobotType = {
'l_original': AppState.leaphyOriginalRobotType,
'l_flitz': AppState.leaphyFlitzRobotType,
'l_click': AppState.leaphyClickRobotType,
'l_uno': AppState.arduinoUnoRobotType,
'l_wifi': AppState.leaphyWiFiRobotType,
'l_code': AppState.genericRobotType
'l_code': AppState.genericRobotType,
'l_flitz_nano': AppState.leaphyFlitzNanoRobotType,
'l_nano': AppState.arduinoNanoRobotType,
}
/* eslint-enable max-len */

private defaultLanguage = new Language('nl', 'Nederlands')
private availableLanguages = [new Language('en', 'English'), this.defaultLanguage]

constructor(private localStorage: LocalStorageService) {
constructor(private localStorage: LocalStorageService, private dialog: MatDialog) {
this.isDesktopSubject$ = new BehaviorSubject<boolean>(true);
this.isDesktop$ = this.isDesktopSubject$.asObservable();
this.availableRobotTypes$ = this.isDesktop$
.pipe(map(isDesktop => {
if (isDesktop) {
return [AppState.leaphyFlitzRobotType, AppState.leaphyOriginalRobotType, AppState.leaphyClickRobotType, AppState.arduinoUnoRobotType]
return [AppState.leaphyFlitzRobotType, AppState.leaphyOriginalRobotType, AppState.leaphyClickRobotType, AppState.arduinoUnoRobotType, AppState.arduinoNanoRobotType]
} else {
return [AppState.leaphyWiFiRobotType]
}
Expand Down Expand Up @@ -139,7 +151,23 @@ export class AppState {
}

public setSelectedRobotType(robotType: RobotType) {
this.selectedRobotTypeSubject$.next(robotType);
// Intercept flitz robots and ask what type of flitz robot: nano, or uno
if (robotType === AppState.leaphyFlitzRobotType) {
this.dialog.open(SelectRobotTypeDialog, {
width: '250px',
data: { boardTypes: ["Flitz Uno", "Flitz Nano"], icons: ["flitz.svg", "flitz.svg"] }
}).afterClosed().subscribe((result: string) => {
if (result === "Flitz Uno") {
robotType = AppState.leaphyFlitzRobotType;
} else if (result === "Flitz Nano") {
robotType = AppState.leaphyFlitzNanoRobotType;
}
this.selectedRobotTypeSubject$.next(robotType);
});

} else {
this.selectedRobotTypeSubject$.next(robotType);
}
}

public setChangedLanguage(language: Language) {
Expand Down
Loading

0 comments on commit 3e440d3

Please sign in to comment.