ota-wizard: implement logic for compilation slide

ios
Norwin 6 years ago
parent fce63e4ac8
commit 7ae033268b

@ -83,6 +83,7 @@
<plugin name="cordova-plugin-ionic-webview" spec="^2.0.0" /> <plugin name="cordova-plugin-ionic-webview" spec="^2.0.0" />
<plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" /> <plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" />
<plugin name="wifiwizard2" spec="~3.1.0" /> <plugin name="wifiwizard2" spec="~3.1.0" />
<plugin name="cordova-plugin-network-information" spec="2.0.1" />
<engine name="android" spec="7.1.1" /> <engine name="android" spec="7.1.1" />
<engine name="browser" spec="5.0.4" /> <engine name="browser" spec="5.0.4" />
</widget> </widget>

10
package-lock.json generated

@ -96,6 +96,11 @@
"resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-4.15.0.tgz", "resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-4.15.0.tgz",
"integrity": "sha512-WlFcBktHnufiu+SB1u2GemEkDrXE94+LUkg59BQL1Tr0j+7EXcNY20JUUFCnQZP+uTJbUxaYZEa36B8UKBBpbA==" "integrity": "sha512-WlFcBktHnufiu+SB1u2GemEkDrXE94+LUkg59BQL1Tr0j+7EXcNY20JUUFCnQZP+uTJbUxaYZEa36B8UKBBpbA=="
}, },
"@ionic-native/network": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@ionic-native/network/-/network-4.17.0.tgz",
"integrity": "sha512-isAZx0CWIGHxl4u7GYkwkertNrSarNXhQQ4iQgqOefDJUtOj78zJsYNVxUWk1MiqTyQrnV9H7+WHWf62JAR82w=="
},
"@ionic-native/splash-screen": { "@ionic-native/splash-screen": {
"version": "4.15.0", "version": "4.15.0",
"resolved": "https://registry.npmjs.org/@ionic-native/splash-screen/-/splash-screen-4.15.0.tgz", "resolved": "https://registry.npmjs.org/@ionic-native/splash-screen/-/splash-screen-4.15.0.tgz",
@ -1959,6 +1964,11 @@
"resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-2.2.0.tgz", "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-2.2.0.tgz",
"integrity": "sha512-mNTJaIRsz83Vntk2d3jrPCnlqEPQsfOJW6U2AzS7WV1T15Jj/STdXI/Uv1vIyvPVd9h1OLF+yu64ZsmQH2VRMQ==" "integrity": "sha512-mNTJaIRsz83Vntk2d3jrPCnlqEPQsfOJW6U2AzS7WV1T15Jj/STdXI/Uv1vIyvPVd9h1OLF+yu64ZsmQH2VRMQ=="
}, },
"cordova-plugin-network-information": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/cordova-plugin-network-information/-/cordova-plugin-network-information-2.0.1.tgz",
"integrity": "sha1-6QQh9DDGq3bUCSI/Jfzvu7zhdpA="
},
"cordova-plugin-splashscreen": { "cordova-plugin-splashscreen": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/cordova-plugin-splashscreen/-/cordova-plugin-splashscreen-5.0.2.tgz", "resolved": "https://registry.npmjs.org/cordova-plugin-splashscreen/-/cordova-plugin-splashscreen-5.0.2.tgz",

@ -23,6 +23,7 @@
"@angular/platform-browser": "5.2.11", "@angular/platform-browser": "5.2.11",
"@angular/platform-browser-dynamic": "5.2.11", "@angular/platform-browser-dynamic": "5.2.11",
"@ionic-native/core": "~4.15.0", "@ionic-native/core": "~4.15.0",
"@ionic-native/network": "^4.17.0",
"@ionic-native/splash-screen": "~4.15.0", "@ionic-native/splash-screen": "~4.15.0",
"@ionic-native/status-bar": "~4.15.0", "@ionic-native/status-bar": "~4.15.0",
"@ionic/storage": "2.2.0", "@ionic/storage": "2.2.0",
@ -31,6 +32,7 @@
"cordova-plugin-device": "^2.0.2", "cordova-plugin-device": "^2.0.2",
"cordova-plugin-ionic-keyboard": "^2.1.3", "cordova-plugin-ionic-keyboard": "^2.1.3",
"cordova-plugin-ionic-webview": "^2.2.0", "cordova-plugin-ionic-webview": "^2.2.0",
"cordova-plugin-network-information": "2.0.1",
"cordova-plugin-splashscreen": "^5.0.2", "cordova-plugin-splashscreen": "^5.0.2",
"cordova-plugin-statusbar": "^2.4.2", "cordova-plugin-statusbar": "^2.4.2",
"cordova-plugin-whitelist": "^1.3.3", "cordova-plugin-whitelist": "^1.3.3",
@ -56,7 +58,8 @@
"ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+" "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
}, },
"cordova-plugin-ionic-keyboard": {}, "cordova-plugin-ionic-keyboard": {},
"wifiwizard2": {} "wifiwizard2": {},
"cordova-plugin-network-information": {}
}, },
"platforms": [ "platforms": [
"android", "android",

@ -8,7 +8,6 @@ import { openSenseApp } from './app.component';
import { HomePage } from '../pages/home/home'; import { HomePage } from '../pages/home/home';
import { ApiProvider } from '../providers/api/api'; import { ApiProvider } from '../providers/api/api';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { OtaWifiProvider } from '../providers/ota-wifi/ota-wifi';
import { OtaWizardPage } from '../pages/ota-wizard/ota-wizard'; import { OtaWizardPage } from '../pages/ota-wizard/ota-wizard';
import { OtaWizardPageModule } from '../pages/ota-wizard/ota-wizard.module'; import { OtaWizardPageModule } from '../pages/ota-wizard/ota-wizard.module';
@ -34,7 +33,6 @@ import { OtaWizardPageModule } from '../pages/ota-wizard/ota-wizard.module';
SplashScreen, SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}, {provide: ErrorHandler, useClass: IonicErrorHandler},
ApiProvider, ApiProvider,
OtaWifiProvider
] ]
}) })
export class AppModule {} export class AppModule {}

@ -1,6 +1,5 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { OtaWifiProvider } from '../../providers/ota-wifi/ota-wifi';
import { OtaWizardPage } from '../ota-wizard/ota-wizard'; import { OtaWizardPage } from '../ota-wizard/ota-wizard';
/** /**
@ -19,13 +18,7 @@ export class BlocklyPage {
constructor( constructor(
public navCtrl: NavController, public navCtrl: NavController,
public navParams: NavParams, public navParams: NavParams) {
private otaWifi: OtaWifiProvider) {
// otaWifi is here only for testing, should later be encapsulated by OtaWizardComponent
console.log('wifi strategy:', otaWifi.strategy)
otaWifi.findSenseboxes()
.then(console.log)
.catch(console.error)
} }
ionViewDidLoad() { ionViewDidLoad() {

@ -38,12 +38,33 @@
</ion-grid> </ion-grid>
</ion-slide> </ion-slide>
<!-- compilation waiting screen -->
<ion-slide> <ion-slide>
<h1>Check internet connection for compilation</h1> <ng-container *ngIf="state.compilation == 'compiling'">
<pre style="text-align: left"> <h2>Compiling your sketch...</h2>
- if connected: background: compile code <ion-spinner item-start name="dots"></ion-spinner>
- if not: enable wifi (manually on iOS) </ng-container>
</pre>
<ng-container *ngIf="state.compilation == 'go-online'">
<h2>You are offline.</h2>
<p>
For compilation, you need to connect to the internet.
Please enable a connection.
</p>
</ng-container>
<ng-container *ngIf="state.compilation == 'done'">
<h2>Sketch successfully compiled.</h2>
<button ion-button large clear icon-end color="primary" (click)="slides.slideNext()">
Continue
<ion-icon name="arrow-forward"></ion-icon>
</button>
</ng-container>
<ng-container *ngIf="state.compilation == 'error'">
<h2>Error compiling your sketch.</h2>
<!-- TODO <p>{{ status }}</p> -->
</ng-container>
</ion-slide> </ion-slide>
<ion-slide> <ion-slide>

@ -1,6 +1,8 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular'; import { IonicPageModule } from 'ionic-angular';
import { OtaWizardPage } from './ota-wizard'; import { OtaWizardPage } from './ota-wizard';
import { Network } from '@ionic-native/network';
import { OtaWifiProvider } from '../../providers/ota-wifi/ota-wifi';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -9,5 +11,9 @@ import { OtaWizardPage } from './ota-wizard';
imports: [ imports: [
IonicPageModule.forChild(OtaWizardPage), IonicPageModule.forChild(OtaWizardPage),
], ],
providers: [
Network,
OtaWifiProvider,
]
}) })
export class OtaWizardPageModule {} export class OtaWizardPageModule {}

@ -1,25 +1,132 @@
import { Component } from '@angular/core'; import {
import { IonicPage, NavController, NavParams } from 'ionic-angular'; Component,
OnDestroy,
OnInit,
ViewChild,
} from '@angular/core'
import {
IonicPage,
Slides,
} from 'ionic-angular'
import { Network } from '@ionic-native/network'
import { Subscription } from 'rxjs/Subscription';
/** import { OtaWifiProvider, WifiStrategy } from '../../providers/ota-wifi/ota-wifi';
* Generated class for the OtaWizardPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
@IonicPage() @IonicPage()
@Component({ @Component({
selector: 'page-ota-wizard', selector: 'page-ota-wizard',
templateUrl: 'ota-wizard.html', templateUrl: 'ota-wizard.html',
}) })
export class OtaWizardPage { export class OtaWizardPage implements OnInit, OnDestroy {
@ViewChild(Slides) slides: Slides
onlineSub: Subscription
offlineSub: Subscription
constructor(public navCtrl: NavController, public navParams: NavParams) { compilationFailed: boolean
state: OtaState = {
isOnline: false,
compiledSketch: undefined,
compilation: 'compiling',
} }
ionViewDidLoad() { constructor(
console.log('ionViewDidLoad OtaWizardPage'); private network: Network,
private otaWifi: OtaWifiProvider,
) {
} }
ngOnInit() {
// try to start compilation already in the background
this.compileSketch()
this.state.isOnline = this.network.type !== 'none'
this.onlineSub = this.network.onConnect().subscribe(() => {
this.state.isOnline = true
// trigger compilation, only when needed
if (this.state.compilation == 'go-online') this.compileSketch()
})
this.offlineSub = this.network.onDisconnect().subscribe(() => {
this.state.isOnline = false
})
}
ngOnDestroy () {
this.onlineSub.unsubscribe()
this.offlineSub.unsubscribe()
}
// call logic for each slide
onSlideChange () {
switch (this.slides.getActiveIndex()) {
case OtaSlides.Intro:
this.slides.lockSwipeToNext(false)
break
case OtaSlides.Compilation:
this.handleCompilation()
break
case OtaSlides.WifiSelection:
this.handleWifiSelection()
break
case OtaSlides.Status:
break
default:
console.warn('unknown slide, please define its logic')
}
}
private handleCompilation () {
this.slides.lockSwipeToNext(!this.state.compiledSketch)
// need to go online for compilation. compilation is retriggered via this.onlineSub
if (!this.state.compiledSketch && !this.state.isOnline) {
switch (this.otaWifi.strategy) {
case WifiStrategy.Automatic:
// TODO: auto connect to previous network, if available
default:
this.state.compilation = 'go-online'
break
}
}
}
private handleWifiSelection () {
this.slides.lockSwipeToNext(true)
console.log('wifi strategy:', this.otaWifi.strategy)
this.otaWifi.findSenseboxes()
.then(console.log)
.catch(console.error)
}
private compileSketch () {
// TODO: mock
this.state.compilation = 'compiling'
setTimeout(() => {
this.state.compiledSketch = 'firmware binary here..'
this.state.compilation = 'done'
this.slides.lockSwipeToNext(false)
}, 4000)
}
}
type OtaState = {
isOnline: boolean,
compiledSketch: any,
compilation: 'compiling' | 'go-online' | 'done' | 'error',
}
// names for the slide indices for easier access
enum OtaSlides {
Intro = 0,
Compilation = 1,
WifiSelection = 2,
Status = 3,
} }

@ -17,32 +17,30 @@ export class OtaWifiProvider {
public strategy: WifiStrategy public strategy: WifiStrategy
constructor(private platform: Platform, private http: HttpClient) { constructor(private platform: Platform, private http: HttpClient) {
this.selectStrategy() this.strategy = this.selectStrategy()
} }
private selectStrategy (): WifiStrategy { private selectStrategy (): WifiStrategy {
try { try {
// check if plugin is available (e.g. not in browser builds) // check if plugin is available (e.g. not in browser builds)
WifiWizard2 WifiWizard2
if (
this.platform.is('android') ||
this.platform.is('ios') && this.platform.version().major >= 11
) {
this.strategy = WifiStrategy.Automatic
} else {
this.strategy = WifiStrategy.Manual
}
} catch (err) { } catch (err) {
this.strategy = WifiStrategy.Unavailable return WifiStrategy.Unavailable
}
if (
this.platform.is('android') ||
this.platform.is('ios') && this.platform.version().major >= 11
) {
return WifiStrategy.Automatic
} }
return this.strategy; return WifiStrategy.Manual
} }
async findSenseboxes (): Promise<string> { async findSenseboxes (): Promise<string> {
if (this.strategy != WifiStrategy.Automatic) if (this.strategy != WifiStrategy.Automatic)
throw Error('can not search for WiFi networks on this platform') throw new Error('can not search for WiFi networks on this platform')
return WifiWizard2.scan() return WifiWizard2.scan()
.then(n => n.filter(n.SSID.includes(SSID_PREFIX))) .then(n => n.filter(n.SSID.includes(SSID_PREFIX)))
@ -51,7 +49,7 @@ export class OtaWifiProvider {
async connectToSensebox (ssid: string): Promise<any> { async connectToSensebox (ssid: string): Promise<any> {
if (this.strategy != WifiStrategy.Automatic) if (this.strategy != WifiStrategy.Automatic)
throw Error('can not connect to WiFi network on this platform') throw new Error('can not connect to WiFi network on this platform')
return this.platform.is('ios') return this.platform.is('ios')
? WifiWizard2.iOSConnectNetwork(ssid) ? WifiWizard2.iOSConnectNetwork(ssid)
@ -66,7 +64,7 @@ export class OtaWifiProvider {
// TODO: replace with "WifiCapabilities". // TODO: replace with "WifiCapabilities".
// makes it easier to check in each functions if required functionality is available // makes it easier to check in each functions if required functionality is available
enum WifiStrategy { export enum WifiStrategy {
Automatic = 'Automatic', // android, iOS 11+ Automatic = 'Automatic', // android, iOS 11+
Manual = 'Manual', // older iOS Manual = 'Manual', // older iOS
Unavailable = 'Unavailable', // browser Unavailable = 'Unavailable', // browser

Loading…
Cancel
Save