Skip to content

Commit

Permalink
Merge pull request #6 from matthew-larner/SP-3-LiveReviewPooling
Browse files Browse the repository at this point in the history
Sp-3 Live Review Pooling
  • Loading branch information
matthew-larner authored Feb 5, 2023
2 parents a17f34f + f11e48d commit fa0d0e9
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 420 deletions.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ services:
networks:
- app
networks:
app:
app:
504 changes: 105 additions & 399 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
},
"dependencies": {
"@types/node": "^13.9.1",
"axios": "^0.21.0",
"axios": "^0.21.4",
"delay": "^4.4.0",
"if-env": "^1.0.4",
"mqtt": "^4.2.4",
"mqtt": "^4.3.7",
"typescript": "^3.8.3",
"yaml": "^1.10.0"
},
Expand Down
51 changes: 41 additions & 10 deletions src/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,55 @@ export interface ControlObjectInterface {

export type StateRequestType = "AreaStateRequest" | "DoorStateRequest" | "InputStateRequest" | "OutputStateRequest";

export interface MonitorUpdatesPayloadInterface {
export interface MonitorStateUpdatesPayloadInterface {
ID: StateRequestType;
RequestType: string;
InputData: {
stateType: string;
timeSinceUpdate: string;
}
InputData: MonitorStateInputData
}

export interface MonitorUpdatesResponseInterface {
export interface MonitorStateUpdatesResponseInterface {
ID: StateRequestType;
Result: {
updateTime: number;
stateData: StateDataInterface[];
}
Result: StateResultInterface
}

export interface StateResultInterface {
updateTime: number;
stateData: StateDataInterface[];
}

export interface StateDataInterface {
ID: string;
PublicState: number;
}

export interface MonitorReviewUpdatesResponseInterface {
ID: string
Result: ReviewDataInterface[]
}

export interface ReviewDataInterface {
ID: string;
Description: string;
MessageCategory: number;
What: string;
Where: string;
WhenTicks: number;
}

export interface MonitorStateInputData {
stateType: string;
timeSinceUpdate: string;
}

export type LiveReviewRequestType = "LiveReviewEvents";

export interface MonitorReviewUpdatesPayloadInterface {
ID: LiveReviewRequestType;
RequestType: LiveReviewRequestType;
InputData: MonitorReviewInputData
}

export interface MonitorReviewInputData {
referenceId: string;
referenceTime: number;
}
4 changes: 2 additions & 2 deletions src/entities/inception.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios, { AxiosError } from 'axios';
import * as delay from 'delay';

import { ControlObjectInterface, MonitorUpdatesResponseInterface } from '../contracts';
import { ControlObjectInterface, MonitorStateUpdatesResponseInterface, MonitorReviewUpdatesResponseInterface } from '../contracts';

let config: any;
let userID = '';
Expand Down Expand Up @@ -178,7 +178,7 @@ export const getControlInputs = async (): Promise<ControlObjectInterface[]> => {
}
};

export const monitorUpdates = async (payload: any[], onUnAuthorizedHandler: () => void): Promise<MonitorUpdatesResponseInterface> => {
export const monitorUpdates = async (payload: any[], onUnAuthorizedHandler: () => void): Promise<MonitorStateUpdatesResponseInterface|MonitorReviewUpdatesResponseInterface> => {
try {
const timeout = (config.polling_timeout ?? 60) * 1000;
const response = await axios.post(`${config.base_url}/monitor-updates`, payload, {
Expand Down
64 changes: 64 additions & 0 deletions src/entities/inceptionLiveReviewPolling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { MonitorReviewUpdatesPayloadInterface, ReviewDataInterface, LiveReviewRequestType } from '../contracts';
import * as inception from './inception';
import * as mqtt from './mqtt';

export const polling = async () => {

const liveReviewEvents = 'LiveReviewEvents';

const publishLiveReviewUpdates = (data: ReviewDataInterface) => {
const topic = `inception/event`;
const { Description, MessageCategory, What, Where } = data;

mqtt.publish(topic, JSON.stringify({
Description,
MessageCategory,
What,
Where
}));
};

let monitorUpdatesPayload: MonitorReviewUpdatesPayloadInterface[];
const initPayload = () => {
monitorUpdatesPayload = [
{
ID: liveReviewEvents,
RequestType: liveReviewEvents,
InputData: {
referenceId: null,
referenceTime: null
}
}
];
}

while (true) {
try {
if (!monitorUpdatesPayload) {
initPayload();
}

console.log('Polling monitor updates with payload ' + JSON.stringify(monitorUpdatesPayload));

const response = await inception.monitorUpdates(monitorUpdatesPayload, initPayload);
const results = response.Result as unknown as ReviewDataInterface[];
const newMonitorUpdatesPayload = [];

for( let result of results) {
publishLiveReviewUpdates(result);
newMonitorUpdatesPayload.push({
ID: liveReviewEvents,
RequestType: liveReviewEvents,
InputData: {
referenceId: result.ID,
referenceTime: result.WhenTicks
}
});
monitorUpdatesPayload = newMonitorUpdatesPayload;
}

} catch (error) {
console.error('Inception polling encountered an error: ', error.message);
}
}
};
9 changes: 5 additions & 4 deletions src/entities/inceptionPolling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MonitorUpdatesPayloadInterface } from '../contracts';
import { MonitorStateUpdatesPayloadInterface, StateResultInterface } from '../contracts';
import * as inception from './inception';
import * as mqtt from './mqtt';
import * as utils from './utils';
Expand Down Expand Up @@ -96,7 +96,7 @@ export const polling = async () => {
'DoorStateRequest': publishDoorStateUpdates
};

let monitorUpdatesPayload: MonitorUpdatesPayloadInterface[];
let monitorUpdatesPayload: MonitorStateUpdatesPayloadInterface[];

const initPayload = () => {
monitorUpdatesPayload = [
Expand Down Expand Up @@ -144,12 +144,13 @@ export const polling = async () => {
console.log('Polling monitor updates with payload ' + JSON.stringify(monitorUpdatesPayload));

const response = await inception.monitorUpdates(monitorUpdatesPayload, initPayload);
const result = response.Result as StateResultInterface;

const handler = stateChangeMapping[response?.ID];

if (handler) {
response.Result.stateData.forEach(item => handler(item.ID, item.PublicState));
monitorUpdatesPayload.find(item => item.ID === response.ID).InputData.timeSinceUpdate = response.Result.updateTime.toString(); // updates `timeSinceUpdate` = 'Result.updateTime' for the new long polling request.
result.stateData.forEach(item => handler(item.ID, item.PublicState));
monitorUpdatesPayload.find(item => item.ID === response.ID).InputData.timeSinceUpdate = result.updateTime.toString(); // updates `timeSinceUpdate` = 'Result.updateTime' for the new long polling request.
}
} catch (error) {
console.error('Inception polling encountered an error: ', error.message);
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { IClientOptions } from 'mqtt';
import * as mqtt from './entities/mqtt';
import * as inception from './entities/inception';
import * as homeAssistant from './entities/homeAssistant';
import * as inceptionPolling from './entities/inceptionPolling';
import * as inceptionStateMonitor from './entities/inceptionPolling';
import * as inceptionLiveReviewMonitor from './entities/inceptionLiveReviewPolling';

const main = async () => {
try {
Expand Down Expand Up @@ -35,7 +36,9 @@ const main = async () => {

await inception.connect(inceptionConfig, publishStatusChange);
await homeAssistant.connect(mqttConfig);
await inceptionPolling.polling();

inceptionStateMonitor.polling();
inceptionLiveReviewMonitor.polling();

} catch (error) {
console.error(error.message);
Expand Down

0 comments on commit fa0d0e9

Please sign in to comment.