Skip to content

Commit

Permalink
Abstract thermometer
Browse files Browse the repository at this point in the history
  • Loading branch information
bradhugh committed Feb 3, 2020
1 parent 098320f commit 99016d9
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 22 deletions.
75 changes: 72 additions & 3 deletions src/IotBbq.App/IotBbq.JsApp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/IotBbq.App/IotBbq.JsApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@bradhugh/Set-System-Clock": "^1.0.5",
"@bradhugh/pi-spi": "^1.2.2",
"drivelist": "^7.0.3",
"noble": "^1.9.1",
"onoff": "^3.2.9"
},
"devDependencies": {
Expand Down
11 changes: 11 additions & 0 deletions src/IotBbq.App/IotBbq.JsApp/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ import { DesignSpiClient } from './services/design/DesignSpiClient';
import { NullGpioFactory } from './services/design/NullGpio';
import { InMemoryStorage } from './services/design/InMemoryStorage';
import { NullExportService } from './services/design/NullExportService';
import { THERM_SVC_TOKEN, IThermometerService } from './services/contracts/IThermometerService';
import { BtThermometer } from './services/BtThermometer';

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
Expand Down Expand Up @@ -122,6 +124,14 @@ export function ExportServiceFactory(
}
}

export function BluetoothThermometerFactory(xplat: XPlatService, spi: ISpiClient): IThermometerService {
if (xplat.isElectron()) {
return new BtThermometer(xplat);
}

return new ThermometerService(spi);
}

@NgModule({
declarations: [
AppComponent,
Expand Down Expand Up @@ -185,6 +195,7 @@ export function ExportServiceFactory(
{ provide: DATA_STORAGE_TOKEN, useClass: IndexedDbDataStorage },
{ provide: SPICLIENT_TOKEN, useFactory: SpiClientFactory, deps: [ XPlatService ] },
{ provide: GPIO_FACTORY_TOKEN, useFactory: GpioFactoryFactory, deps: [ XPlatService ] },
{ provide: THERM_SVC_TOKEN, useFactory: BluetoothThermometerFactory, deps: [ XPlatService, SPICLIENT_TOKEN ] },
],
bootstrap: [AppComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PhaseChooserService } from '../../services/PhaseChooserService';
import { IDataStorage, DATA_STORAGE_TOKEN } from '../../services/contracts/IDataStorage';
import { TimeSpan } from '../../services/TimeSpan';
import { AlarmService, AlarmPriority } from '../../services/AlarmService';
import { ThermometerService, ThermometerState } from '../../services/ThermometerService';
import { IThermometerService, ThermometerState, THERM_SVC_TOKEN } from '../../services/contracts/IThermometerService';

@Component({
selector: 'app-bbq-item',
Expand Down Expand Up @@ -35,7 +35,7 @@ export class BbqItemComponent implements OnInit {
public isDisconnected = false;

constructor(
private thermometerService: ThermometerService,
@Inject(THERM_SVC_TOKEN) private thermometerService: IThermometerService,
private alarmService: AlarmService,
private phaseChooserService: PhaseChooserService,
@Inject(DATA_STORAGE_TOKEN) private dataStorage: IDataStorage,
Expand Down Expand Up @@ -66,7 +66,7 @@ export class BbqItemComponent implements OnInit {
public async nextPhaseClicked(event: Event) {
event.stopPropagation();

// Not sure I need to acually do much here
// Not sure I need to actually do much here
const nextPhase = await this.phaseChooserService.chooseNextPhase(this.item);

// Phase has changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Component, OnInit, Input, Inject } from '@angular/core';
import { ISmokerModel } from '../../model/SmokerSettings';
import { SmokerEditorService } from '../../services/SmokerEditorService';
import { Observable, timer } from 'rxjs';
import { ThermometerService, ThermometerState } from '../../services/ThermometerService';
import { AlarmService, AlarmPriority } from '../../services/AlarmService';
import { IDataStorage, DATA_STORAGE_TOKEN } from '../../services/contracts/IDataStorage';
import { IThermometerService, ThermometerState, THERM_SVC_TOKEN } from '../../services/contracts/IThermometerService';

@Component({
selector: 'app-smoker',
Expand Down Expand Up @@ -38,7 +38,7 @@ export class SmokerComponent implements OnInit {

constructor(
private smokerEditor: SmokerEditorService,
private thermometer: ThermometerService,
@Inject(THERM_SVC_TOKEN) private thermometer: IThermometerService,
private alarmService: AlarmService,
@Inject(DATA_STORAGE_TOKEN) private dataStorage: IDataStorage,
) { }
Expand Down
56 changes: 56 additions & 0 deletions src/IotBbq.App/IotBbq.JsApp/src/app/services/BtThermometer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { IThermometerService, ITemps, ThermometerState } from './contracts/IThermometerService';

import * as noble from 'noble';
import { XPlatService } from './XPlatService';

export class BtThermometer implements IThermometerService {

private initializing = false;

constructor(private xplat: XPlatService) {
}

public async readThermometer(probeNumber: number): Promise<ITemps> {
if (!this.initializing) {
this.initializing = true;
await this.initializeRemote();
}

return {
celcius: 0,
farenheight: 0,
kelvin: 0,
state: ThermometerState.Disconnected
};
}

private async powerOn(): Promise<void> {
new Promise((resolve, reject) => {
noble.on('stateChange', (state) => {
console.log(`State change ${state}`);
if (state === 'poweredOn') { resolve(); }
if (state === 'poweredOff') { reject(new Error('Bluetooth failed to initialize.')); }
});
});
}

private async startScanning(): Promise<void> {
return new Promise((resolve, reject) => {
noble.startScanning((err) => {
if (err) {
return reject(err);
}

resolve();
});
});
}

private async initializeRemote(): Promise<void> {
console.log('PowerOn');
await this.powerOn();
console.log('StartScanning');
await this.startScanning();
console.log('Done');
}
}
17 changes: 3 additions & 14 deletions src/IotBbq.App/IotBbq.JsApp/src/app/services/ThermometerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,15 @@ import { SPICLIENT_TOKEN, ISpiClient } from './contracts/ISpiClient';
import { Mcp3008, Channels, Channel } from './Mcp3008';
import { TempUtils } from './TempUtils';
import { Utility } from './Utility';

export enum ThermometerState {
Disconnected,
Connected,
}

export interface ITemps {
state: ThermometerState;
kelvin: number;
celcius: number;
farenheight: number;
}
import { ThermometerState, IThermometerService, ITemps } from './contracts/IThermometerService';

interface CoefficientSet {
A: number;
B: number;
C: number;
}

export class ThermometerService {
export class ThermometerService implements IThermometerService {

private static inputVoltage = 3.3;

Expand Down Expand Up @@ -97,7 +86,7 @@ export class ThermometerService {
// TODO: Check this check, not sure how this would be possible
if (resistance !== NaN) {
temps.state = ThermometerState.Connected;
temps.kelvin = TempUtils.resistanceToTemp(this.coefficients.A, this.coefficients.B, this.coefficients.C, resistance);
temps.kelvin = TempUtils.resistanceToTemp(this.coefficients.A, this.coefficients.B, this.coefficients.C, resistance);
temps.celcius = TempUtils.kelvinToCelcius(temps.kelvin);
temps.farenheight = TempUtils.celciusToFarenheight(temps.celcius);
}
Expand Down
3 changes: 3 additions & 0 deletions src/IotBbq.App/IotBbq.JsApp/src/app/services/XPlatService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as path from 'path';
import * as onoff from 'onoff';
import * as pispi from '@bradhugh/pi-spi';
import * as drivelist from 'drivelist';
import * as noble from 'noble';
import { DateTimeControl } from '@bradhugh/Set-System-Clock';

@Injectable()
Expand All @@ -28,6 +29,7 @@ export class XPlatService {
public pispi: typeof pispi;
public drivelist: typeof drivelist;
public dateTimeControl: DateTimeControl;
public noble: typeof noble;

constructor() {
// Conditional imports
Expand All @@ -44,6 +46,7 @@ export class XPlatService {
// Remote native modules
this.drivelist = this.remote.require('drivelist');
this.dateTimeControl = new (this.remote.require('@bradhugh/Set-System-Clock').DateTimeControl)();
this.noble = this.remote.require('noble');

// These native modules are only used on the PI
if (this.isArm()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { InjectionToken } from '@angular/core';

export const THERM_SVC_TOKEN = new InjectionToken<IThermometerService>('THERM_SVC_TOKEN');

export enum ThermometerState {
Disconnected,
Connected,
}

export interface ITemps {
state: ThermometerState;
kelvin: number;
celcius: number;
farenheight: number;
}

export interface IThermometerService {
readThermometer(probeNumber: number): Promise<ITemps>;
}

0 comments on commit 99016d9

Please sign in to comment.