Skip to content

Commit

Permalink
Support Tasmota Air-Conditioning IR Transmitter #148
Browse files Browse the repository at this point in the history
- Implement cache and IR/RF commands cache manager
- Add FetchCommandsAvailable option to the device kind
- Update docs
- Fix grammar
  • Loading branch information
haimkastner committed Jul 4, 2020
1 parent c2bf8d0 commit 495aa67
Show file tree
Hide file tree
Showing 34 changed files with 810 additions and 621 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ In addination I made a [Linux deployment tutorial](./docs/LINUX.md) for a Linux
- Tasmota

- Switch (tested with [this](https://www.gearbest.com/robot-vacuum-accessories/pp_009661965579.html?wid=1433363) and [this](https://www.gearbest.com/alarm-systems/pp_009227681096.html?wid=1433363))
- Air-conditioning (IR Transmitter) (tested with [this](https://www.aliexpress.com/item/33004692351.html) (after [flashing to Tasmota](https://blog.castnet.club/en/blog/flashing-tasmota-on-tuya-ir-bridge))

- [IFTTT](https://ifttt.com/discover) module. [module use documentation](./backend/src/modules/ifttt/README.md)..

Expand Down
8 changes: 8 additions & 0 deletions backend/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"cSpell.words": [
"Tasmota",
"Tuya",
"Yeelight",
"broadlink"
]
}
5 changes: 5 additions & 0 deletions backend/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 backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"await-semaphore": "^0.1.3",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"broadlink-ir-converter": "^1.0.1",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"child-process-promise": "^2.2.1",
Expand Down
4 changes: 2 additions & 2 deletions backend/scripts/buildVersion.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ const git = simplegit();

const buildVersionInfo = async() => {
const tags = await git.tags();
const commintHash = await git.revparse(['--short', 'HEAD']);
const commitHash = await git.revparse(['--short', 'HEAD']);
const rawTimestamp = await git.show(['-s', '--format=%ct']);

const timestamp = +rawTimestamp * 1000;

fse.writeFileSync(path.join(__dirname, '../dist', 'versionInfo.json'), JSON.stringify({
version: tags.latest,
commintHash,
commitHash,
timestamp,
}));
}
Expand Down
6 changes: 3 additions & 3 deletions backend/src/business-layer/minionsBl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ export class MinionsBl {
/**
* Check if token reqired and not exist.
*/
if (deviceKind.isTokenRequierd && !minionToCheck.device.token) {
if (deviceKind.isTokenRequired && !minionToCheck.device.token) {
return {
responseCode: 2409,
message: 'token is requird',
Expand All @@ -684,7 +684,7 @@ export class MinionsBl {
/**
* Check if id reqired and not exist.
*/
if (deviceKind.isIdRequierd && !minionToCheck.device.deviceId) {
if (deviceKind.isIdRequired && !minionToCheck.device.deviceId) {
return {
responseCode: 3409,
message: 'id is required',
Expand Down Expand Up @@ -716,7 +716,7 @@ export class MinionsBl {
/**
* ignore user selection and set corrent minion type based on model.
*/
minionToCheck.minionType = deviceKind.suppotedMinionType;
minionToCheck.minionType = deviceKind.supportedMinionType;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion backend/src/business-layer/timingsBl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export class TimingsBl {
*/
private async timeoutTiming(now: Moment, timing: Timing, timingProperties: TimeoutTiming): Promise<void> {
const timeoutMoment = moment(timingProperties.startDate);
timeoutMoment.add(timingProperties.durationInMimutes, 'minute');
timeoutMoment.add(timingProperties.durationInMinutes, 'minute');

/**
* If its new trigger timing.
Expand Down
4 changes: 2 additions & 2 deletions backend/src/controllers/iftttController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
IftttActionTriggered,
IftttActionTriggeredRequest,
IftttIntegrationSettings,
IftttRawActionTriggerd,
IftttRawActionTriggered,
} from '../models/sharedInterfaces';

@Tags('Ifttt')
Expand Down Expand Up @@ -59,7 +59,7 @@ export class IftttController extends Controller {
@Response<ErrorResponse>(501, 'Server error')
@Security('iftttAuth')
@Post('/trigger/minions/raw/')
public async triggeredSomeAction(@Body() iftttRawActionTriggerd: IftttRawActionTriggerd): Promise<void> {
public async triggeredSomeAction(@Body() iftttRawActionTriggerd: IftttRawActionTriggered): Promise<void> {
const { apiKey, minionId, setStatus } = iftttRawActionTriggerd;
await IftttIntegrationBlSingleton.triggeredMinionAction(minionId, {
apiKey,
Expand Down
6 changes: 3 additions & 3 deletions backend/src/controllers/minionsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
MinionSetRoomName,
MinionStatus,
MinionTimeline,
ScaningStatus,
ScanningStatus,
SetMinionAutoTurnOff,
VersionUpdateStatus,
} from '../models/sharedInterfaces';
Expand Down Expand Up @@ -140,9 +140,9 @@ export class MinionsController extends Controller {
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@Get('rescan')
public async getSescaningMinionsStatus(): Promise<ScaningStatus> {
public async getSescaningMinionsStatus(): Promise<ScanningStatus> {
return {
scaningStatus: await MinionsBlSingleton.getScaningStatus(),
scanningStatus: await MinionsBlSingleton.getScaningStatus(),
};
}

Expand Down
24 changes: 15 additions & 9 deletions backend/src/models/sharedInterfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,22 +139,28 @@ export declare interface DeviceKind {
/**
* Is the device require a token for communication API.
*/
isTokenRequierd: boolean;
isTokenRequired: boolean;

/**
* Is device require id for communication API.
*/
isIdRequierd: boolean;
isIdRequired: boolean;

/**
* Supported minion type for the current device.
*/
suppotedMinionType: MinionTypes;
supportedMinionType: MinionTypes;

/**
* Some of the devices supported recording (for example IR transmitter).
*/
isRecordingSupported: boolean;

/**
* Whenever the device and module supported fetching commands data from
* the https://github.com/casanet/rf-commands-repo project
*/
isFetchCommandsAvailable: boolean;
}

/**
Expand Down Expand Up @@ -378,7 +384,7 @@ export declare interface TimeoutTiming {
/**
* Duration to activate timing from the start timeout time in minutes.
*/
durationInMimutes: number;
durationInMinutes: number;
}

/**
Expand Down Expand Up @@ -707,8 +713,8 @@ export declare interface IftttActionTriggered extends IftttActionTriggeredReques
setStatus: SwitchOptions;
}

/** Ifttt trigger with all request data in one JSON struct. */
export declare interface IftttRawActionTriggerd extends IftttActionTriggeredRequest {
/** Ifttt trigger with all request data in one JSON structure. */
export declare interface IftttRawActionTriggered extends IftttActionTriggeredRequest {
minionId: string;
setStatus: SwitchOptions;
}
Expand All @@ -724,7 +730,7 @@ export declare interface VersionInfo {
/** Latest version (Git Tag) name */
version: string;
/** Current local master/HEAD commit hash */
commintHash: string;
commitHash: string;
/** Time stamp of HEAD commit in UTC format */
timestamp: number;
}
Expand All @@ -733,8 +739,8 @@ export declare interface VersionInfo {
export declare type ProgressStatus = 'inProgress' | 'finished' | 'fail';

/** Scanning progress status */
export declare interface ScaningStatus {
scaningStatus: ProgressStatus;
export declare interface ScanningStatus {
scanningStatus: ProgressStatus;
}

/** Version update progress status */
Expand Down
45 changes: 5 additions & 40 deletions backend/src/modules/brandModuleBase.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as fse from 'fs-extra';
import * as path from 'path';
import { PullBehavior } from 'pull-behavior';
import { BehaviorSubject } from 'rxjs';
Expand All @@ -16,7 +15,7 @@ export abstract class BrandModuleBase {
/**
* Cache file pull path.
*/
private get cacheFilePath(): string {
protected get cacheFilePath(): string {
return `${path.join(CACHE_DIRECTORY, this.brandName)}.json`;
}

Expand Down Expand Up @@ -47,16 +46,16 @@ export abstract class BrandModuleBase {

/**
* Get current status of minion. (such as minion status on off etc.)
* @param miniom minion to get status for.
* @param minion minion to get status for.
*/
public abstract getStatus(miniom: Minion): Promise<MinionStatus | ErrorResponse>;
public abstract getStatus(minion: Minion): Promise<MinionStatus | ErrorResponse>;

/**
* Set minion new status. (such as turn minion on off etc.)
* @param miniom minion to set status for.
* @param minion minion to set status for.
* @param setStatus the new status to set.
*/
public abstract setStatus(miniom: Minion, setStatus: MinionStatus): Promise<void | ErrorResponse>;
public abstract setStatus(minion: Minion, setStatus: MinionStatus): Promise<void | ErrorResponse>;

/**
* Record data for currrent minion status.
Expand Down Expand Up @@ -89,38 +88,4 @@ export abstract class BrandModuleBase {
* Used for cleaning up communication before re-reading data, after communication auth changed or just hard reset module etc.
*/
public abstract refreshCommunication(): Promise<void>;

/**
* Get cache JSON data sync.
* Use it in init only. else the app will black until read finish.
*/
protected getCacheDataSync(): any {
try {
return fse.readJSONSync(this.cacheFilePath);
} catch (error) {
return undefined;
}
}

/**
* Get cache JSON data.
*/
protected async getCacheData(): Promise<any> {
const data = await fse.readJSON(this.cacheFilePath).catch(err => {
logger.warn(`Fail to read ${this.cacheFilePath} cache file, ${err}`);
throw new Error('Fail to read cache data');
});
return data;
}

/**
* Save JSON to module cache.
* @param data Data to save in cache.
*/
protected async setCacheData(data: any): Promise<void> {
await fse.outputFile(this.cacheFilePath, JSON.stringify(data, null, 2)).catch(err => {
logger.warn(`Fail to write ${this.cacheFilePath} cache file, ${err}`);
throw new Error('Fail to write cache data');
});
}
}
Loading

0 comments on commit 495aa67

Please sign in to comment.