Skip to content

Commit

Permalink
Send home state to AI
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Gilles committed Oct 18, 2024
1 parent 558adf9 commit b2a57c0
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 1 deletion.
20 changes: 20 additions & 0 deletions server/lib/gateway/gateway.forwardMessageToOpenAI.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const logger = require('../../utils/logger');
const { Error429 } = require('../../utils/httpErrors');

const intentTranslation = {
Expand Down Expand Up @@ -26,10 +27,28 @@ const disableOpenAiFirstReply = new Set(['GET_TEMPERATURE', 'GET_HUMIDITY']);
*/
async function forwardMessageToOpenAI({ message, image, previousQuestions, context }) {
try {
const devices = this.stateManager.getAllKeys('device').map((deviceSelector) => {
const d = this.stateManager.get('device', deviceSelector);
return {
name: d.name,
room: d.room ? d.room.name : '',
features: d.features.map((f) => ({
name: f.name,
selector: f.selector,
category: f.category,
type: f.type,
last_value: f.last_value,
last_value_changed: f.last_value_changed,
unit: f.unit,
})),
};
});

const response = await this.openAIAsk({
question: message.text,
image,
previous_questions: previousQuestions,
devices,
});

const classification = {};
Expand Down Expand Up @@ -65,6 +84,7 @@ async function forwardMessageToOpenAI({ message, image, previousQuestions, conte

return classification;
} catch (e) {
logger.warn(e);
if (e instanceof Error429) {
await this.message.replyByIntent(message, 'openai.request.tooManyRequests', context);
} else {
Expand Down
12 changes: 12 additions & 0 deletions server/lib/state/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ function get(entity, entitySelector) {
return this.state[entity][entitySelector].get();
}

/**
* @description Return all keys.
* @param {string} entity - The type of entity we should get the value from.
* @returns {any} Return the full state in store.
* @example
* stateManager.get('device', 'main-lamp');
*/
function getAllKeys(entity) {
return Object.keys(this.state[entity]);
}

/**
* @description Return the value of a key in the store.
* @param {string} entity - The type of entity we should get the value from.
Expand Down Expand Up @@ -85,5 +96,6 @@ StateManager.prototype.setState = setState;
StateManager.prototype.deleteState = deleteState;
StateManager.prototype.get = get;
StateManager.prototype.getKey = getKey;
StateManager.prototype.getAllKeys = getAllKeys;

module.exports = StateManager;
115 changes: 114 additions & 1 deletion server/test/lib/gateway/gateway.forwardMessageToOpenAI.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { expect } = require('chai');
const proxyquire = require('proxyquire').noCallThru();
const EventEmitter = require('events');

const StateManager = require('../../../lib/state');
const GladysGatewayClientMock = require('./GladysGatewayClientMock.test');

const event = new EventEmitter();
Expand Down Expand Up @@ -48,7 +49,88 @@ describe('gateway.forwardMessageToOpenAI', () => {
getEntityIdByName: fake.returns('14a8ad23-78fa-45e4-8583-f5452792818d'),
};
const serviceManager = {};
const stateManager = {};
const stateManager = new StateManager(event);
stateManager.setState('device', 'co2-sensor', {
id: 'bd2eaaef-5baa-4aa6-8c94-ccce01026a53',
service_id: '59d7e9e2-a5a5-43b0-8796-287e00670355',
room_id: '3dc8243a-983f-45bc-94e8-f0c651b78c5d',
name: 'Capteur salon',
selector: 'mqtt-test',
model: null,
external_id: 'mqtt:test',
should_poll: false,
poll_frequency: null,
created_at: '2024-08-10T07:34:51.798Z',
updated_at: '2024-10-18T02:00:49.733Z',
features: [
{
id: '31fc42aa-f338-40c1-bcc0-c14d37470e71',
device_id: 'bd2eaaef-5baa-4aa6-8c94-ccce01026a53',
name: 'Batterie',
selector: 'mqtt-battery',
external_id: 'mqtt:battery',
category: 'battery',
type: 'integer',
read_only: true,
keep_history: true,
has_feedback: false,
unit: 'percent',
min: 0,
max: 100,
last_value: null,
last_value_string: null,
last_value_changed: null,
last_hourly_aggregate: null,
last_daily_aggregate: null,
last_monthly_aggregate: null,
created_at: '2024-10-04T01:10:45.283Z',
updated_at: '2024-10-04T01:11:22.787Z',
},
{
id: '444b306d-5a2c-49f6-a8a5-ffe2a1d7cb11',
device_id: 'bd2eaaef-5baa-4aa6-8c94-ccce01026a53',
name: 'Niveau de Co2',
selector: 'mqtt-co2',
external_id: 'mqtt:co2',
category: 'co2-sensor',
type: 'integer',
read_only: true,
keep_history: true,
has_feedback: false,
unit: 'ppm',
min: 0,
max: 100000,
last_value: 1200,
last_value_string: null,
last_value_changed: '2024-10-18T01:40:12.042Z',
last_hourly_aggregate: null,
last_daily_aggregate: null,
last_monthly_aggregate: null,
created_at: '2024-10-04T01:11:22.783Z',
updated_at: '2024-10-18T02:01:16.000Z',
},
],
params: [],
room: {
id: '3dc8243a-983f-45bc-94e8-f0c651b78c5d',
house_id: 'ec0e36a8-f370-4157-9249-3892a6e3a52c',
name: 'salon',
selector: 'salon',
created_at: '2024-10-11T06:43:37.620Z',
updated_at: '2024-10-11T06:43:37.620Z',
},
service: {
id: '59d7e9e2-a5a5-43b0-8796-287e00670355',
pod_id: null,
name: 'mqtt',
selector: 'mqtt',
version: '0.1.0',
has_message_feature: false,
status: 'RUNNING',
created_at: '2024-08-08T12:59:46.450Z',
updated_at: '2024-10-18T02:08:20.564Z',
},
});
gateway = new Gateway(
variable,
event,
Expand Down Expand Up @@ -78,6 +160,37 @@ describe('gateway.forwardMessageToOpenAI', () => {
room: 'living room',
});
const classification = await gateway.forwardMessageToOpenAI({ message, previousQuestions, context });
assert.calledWith(gateway.gladysGatewayClient.openAIAsk, {
question: 'Turn on the light in the living room',
devices: [
{
name: 'Capteur salon',
room: 'salon',
features: [
{
name: 'Batterie',
selector: 'mqtt-battery',
category: 'battery',
type: 'integer',
last_value: null,
last_value_changed: null,
unit: 'percent',
},
{
name: 'Niveau de Co2',
selector: 'mqtt-co2',
category: 'co2-sensor',
type: 'integer',
last_value: 1200,
last_value_changed: '2024-10-18T01:40:12.042Z',
unit: 'ppm',
},
],
},
],
image: undefined,
previous_questions: [],
});
expect(classification).to.deep.equal({
entities: [
{
Expand Down
8 changes: 8 additions & 0 deletions server/test/lib/state/state.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ describe('state', () => {
const userSleepState = stateManager.getKey('user', 'tony', 'sleep');
expect(userSleepState).to.equal('asleep');
});
it('should get all users keys', async () => {
const stateManager = new StateManager(event);
stateManager.setState('user', 'tony', {
sleep: 'asleep',
});
const keys = stateManager.getAllKeys('user');
expect(keys).to.deep.equal(['tony']);
});
it('should return null', async () => {
const stateManager = new StateManager(event);
const userSleepState = stateManager.getKey('user', 'tony', 'sleep');
Expand Down

0 comments on commit b2a57c0

Please sign in to comment.