Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
async getDeviceManifest(deviceKind) {
if (this._cachedManifests.has(deviceKind))
return this._cachedManifests.get(deviceKind);
const manifestPath = path.resolve(path.dirname(module.filename), '../' + deviceKind + '/manifest.tt');
const ourMetadata = (await util.promisify(fs.readFile)(manifestPath)).toString();
const ourParsed = ThingTalk.Grammar.parse(ourMetadata);
ourParsed.classes[0].annotations.version = new ThingTalk.Ast.Value.Number(-1);
if (!ourParsed.classes[0].is_abstract) {
try {
// ourMetadata might lack some of the fields that are in the
// real metadata, such as api keys and OAuth secrets
// for that reason we fetch the metadata for thingpedia as well,
// and fill in any missing parameter
const officialMetadata = await super.getDeviceCode(deviceKind);
const officialParsed = ThingTalk.Grammar.parse(officialMetadata);
const ourConfig = ourParsed.classes[0].config;
ourConfig.in_params = ourConfig.in_params.filter((ip) => !ip.value.isUndefined);
const ourConfigParams = new Set(ourConfig.in_params.map((ip) => ip.name));
const officialConfig = officialParsed.classes[0].config;
[(almond) => {
almond.askQuestion(null, 'org.thingpedia.builtin.test', ThingTalk.Type.Number, 'What is the answer to life the universe and everything?').then((v) => {
assert.strictEqual(v, 42);
});
// inject a meaningless intent so we synchronize the two concurrent tasks
return almond.handleParsedCommand({ code: ['bookkeeping', 'special', 'special:wakeup'], entities: {} });
},
`>> What is the answer to life the universe and everything?
sendUtterance(utterance, expecting, choices) {
const store = 'no';
const data = {
q: utterance,
store: store,
thingtalk_version: ThingTalk.version,
};
if (expecting)
data.expect = String(expecting);
let url = `${this._baseUrl}/query?${qs.stringify(data)}`;
// we need to do this one by hand because of the peculiar encoding
// of the keys (we must not escape [ and ])
if (choices) {
choices.forEach((c, i) => {
if (c)
url += `&choices[${i}]=${encodeURIComponent(c.title)}`;
});
}
return Tp.Helpers.Http.get(url).then((data) => {
const choices = this._allContexts.get(this._context);
for (let token of uniform(choices, this._rng).split(' ')) {
// replace entities and undo penn tree bank tokenization
if (/^[A-Z]/.test(token)) { // entity
if (!this._assignedEntities[token]) {
console.log(this._context, this._targetCode, this._assignedEntities);
throw new Error(`Missing entity ${token} (present in the context sentence, not in the context code)`);
}
token = this._assignedEntities[token].display;
}
context_utterance = this._detokenizer(context_utterance, prevtoken, token);
prevtoken = token;
}
for (let [, slot] of context.iterateSlots()) {
if (slot instanceof ThingTalk.Ast.Selector)
continue;
if (slot.value.isUndefined) {
assistant_action = 'slot-fill:' + slot.name;
break;
}
}
if (assistant_action === null) {
if (context.isProgram && context.rules.every((r) => !r.stream && r.actions.every((a) => a.isInvocation && a.invocation.selector.isBuiltin)))
assistant_action = 'result';
else
assistant_action = 'confirm';
}
}
// remove flags
const id = this._id.replace(/^R?P?S/, '');
async function loadClassDef(dbClient, req, kind, classCode, datasetCode) {
const tpClient = new ThingpediaClient(req.user.developer_key, req.user.locale, dbClient);
const schemaRetriever = new ThingTalk.SchemaRetriever(tpClient, null, true);
let parsed;
try {
parsed = await ThingTalk.Grammar.parseAndTypecheck(`${classCode}\n${datasetCode}`, schemaRetriever, true);
} catch(e) {
if (e.name === 'SyntaxError' && e.location) {
let lineNumber = e.location.start.line;
// add 1 for the \n that we add to separate classCode and datasetCode
console.log(classCode);
const classLength = 1 + classCode.split('\n').length;
const fileName = lineNumber > classLength ? 'dataset.tt' : 'manifest.tt';
// mind the 1-based line numbers...
lineNumber = lineNumber > classLength ? lineNumber - classLength + 1 : lineNumber;
throw new ValidationError(`Syntax error in ${fileName} line ${lineNumber}: ${e.message}`);
} else {
throw new ValidationError(e.message);
}
}
if (!parsed.isMeta || parsed.classes.length !== 1 ||
}
this._state = 'loading';
let { id, utterance, preprocessed, target_code: oldTargetCode } = line;
this._utterance = utterance;
if (!oldTargetCode)
oldTargetCode = preprocessed;
if (!id)
id = this._serial;
const parsed = await this._parser.sendUtterance(utterance, /* tokenized */ false, /* context */ undefined);
if (oldTargetCode) {
try {
const program = ThingTalk.NNSyntax.fromNN(oldTargetCode.split(' '), parsed.entities);
await program.typecheck(this._schemas);
} catch(e) {
console.log(`Sentence ${id}'s existing code is incorrect: ${e}`); //'
oldTargetCode = undefined;
}
}
if (oldTargetCode)
parsed.candidates.unshift({ code: oldTargetCode.split(' '), score: 'Infinity' });
this._state = 'top3';
this._id = id;
this._preprocessed = parsed.tokens.join(' ');
this._entities = parsed.entities;
this._candidates = (await Promise.all(parsed.candidates.map(async (cand) => {
try {
const program = ThingTalk.NNSyntax.fromNN(cand.code, parsed.entities);
function rowsToExamples(rows, { editMode = false, skipId = false }) {
// coalesce by target code
// note: this code is designed to be fast, and avoid parsing the examples in the common
// case of up-to-date thingpedia
let uniqueCode = new Map;
for (let row of rows) {
let targetCode = row.target_code || row.program;
if (!targetCode)
throw new InternalError('E_DATASET_CORRUPT', `Invalid example ${row.id}, missing program`);
if (/^[ \r\n\t\v]*let[ \r\n\t\v]/.test(targetCode)) {
// forward compatibility: convert the declaration to example syntax
const parsed = ThingTalk.Grammar.parse(targetCode);
const declaration = parsed.declarations[0];
const example = new ThingTalk.Ast.Example(-1,
declaration.type === 'table' ? 'query' : declaration.type,
declaration.args,
declaration.value,
[], [], {});
targetCode = example.prettyprint('').trim();
} else if (!/^[ \r\n\t\v]*(query|action|stream|program)[ \r\n\t\v]/.test(targetCode)) {
targetCode = `program := ${targetCode}`;
}
if (uniqueCode.has(targetCode)) {
const ex = uniqueCode.get(targetCode);
ex.utterances.push(row.utterance);
ex.preprocessed.push(row.preprocessed);
if (unit != '°C' && unit != 'C') {
if (unit === '°F' || unit === 'F')
value = Units.transformToBaseUnit(value, 'F');
else if (unit === 'K')
value = Units.transformToBaseUnit(value, 'K');
else
throw new Error(`Unrecognized unit ${unit}`)
}
} else if (this.device_class === 'pressure') {
if (unit != 'Pa') {
if (unit === 'hPa' || unit === 'hpa')
value *= 100;
else if (unit === 'mbar')
value = Units.transformToBaseUnit(value * 0.001, 'bar');
else if (['bar', 'psi', 'mmHg', 'inHg', 'atm'].includes(unit))
value = Units.transformToBaseUnit(value * 0.001, unit);
else
throw new Error(`Unrecognized unit ${unit}`)
}
}
return [{state: undefined, value: value}];
} else if (this.domain === 'binary_sensor') {
let state = this.deviceStateMapping[this.state.state];
if (['gas', 'smoke'].includes(this.device_class)) {
state = state === 'detecting' ? this.device_class : 'nothing';
}
return [{state: state, value: undefined}];
}
}
// note: subscribe_ must NOT be async, or an ImplementationError will occur at runtime
let value = parseFloat(this.state.state);
if (this.device_class === 'temperature') {
if (unit != '°C' && unit != 'C') {
if (unit === '°F' || unit === 'F')
value = Units.transformToBaseUnit(value, 'F');
else if (unit === 'K')
value = Units.transformToBaseUnit(value, 'K');
else
throw new Error(`Unrecognized unit ${unit}`)
}
} else if (this.device_class === 'pressure') {
if (unit != 'Pa') {
if (unit === 'hPa' || unit === 'hpa')
value *= 100;
else if (unit === 'mbar')
value = Units.transformToBaseUnit(value * 0.001, 'bar');
else if (['bar', 'psi', 'mmHg', 'inHg', 'atm'].includes(unit))
value = Units.transformToBaseUnit(value * 0.001, unit);
else
throw new Error(`Unrecognized unit ${unit}`)
}
}
return [{state: undefined, value: value}];
} else if (this.domain === 'binary_sensor') {
let state = this.deviceStateMapping[this.state.state];
if (['gas', 'smoke'].includes(this.device_class)) {
state = state === 'detecting' ? this.device_class : 'nothing';
}
return [{state: state, value: undefined}];
}
}
// note: subscribe_ must NOT be async, or an ImplementationError will occur at runtime
// -*- mode: js; indent-tabs-mode: nil; js-basic-offset: 4 -*-
//
// This file is part of io.home-assistant
//
// Copyright 2019 Xiaomeng Jin
//
// See LICENSE for details
"use strict";
const Units = require('thingtalk').Units
const HomeAssistantDevice = require('./base');
module.exports = class HomeAssistantSensor extends HomeAssistantDevice {
constructor(engine, state, master, entityId) {
super(engine, state, master, entityId);
const [domain,] = entityId.split('.');
this.domain = domain;
this.device_class = this.state.attributes.device_class;
if (['binary_sensor', 'cover'].includes(this.domain)) {
let supportedDeviceClasses = {
battery: {
on: 'low',
off: 'normal'
},
cold: {