-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(new-plugin): eliza samsung smarthings plugin (#2678)
* fix(plugin-depin): sentientAI description (#2668) * client-eliza-home client-eliza-home * basic import fixes --------- Co-authored-by: alex <152680487+bodhi-crypo@users.noreply.github.com> Co-authored-by: Sayo <hi@sayo.wtf>
- Loading branch information
1 parent
34ebf70
commit c9c7434
Showing
25 changed files
with
1,442 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"name": "@elizaos/client-eliza-home", | ||
"version": "0.1.0", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*" | ||
}, | ||
"devDependencies": { | ||
"tsup": "8.3.5" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts", | ||
"dev": "tsup --format esm --dts --watch", | ||
"lint": "eslint . --fix" | ||
} | ||
} |
109 changes: 109 additions & 0 deletions
109
packages/client-eliza-home/src/actions/control_device.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { | ||
Action, | ||
ActionExample, | ||
Content, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
State, | ||
} from "@elizaos/core"; | ||
import { SmartHomeManager } from "../smart_home.ts"; | ||
import { smartThingsApi } from "../services/smart_things_api.ts"; | ||
import { deviceStateProvider } from "../providers/device_state.ts"; | ||
|
||
export const controlDeviceAction = { | ||
name: "CONTROL_DEVICE", | ||
similes: ["DEVICE_CONTROL", "SMART_HOME_CONTROL", "HOME_CONTROL"], | ||
description: "Controls smart home devices with specific commands", | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
const keywords = [ | ||
"turn on", | ||
"turn off", | ||
"switch", | ||
"toggle", | ||
"set", | ||
"change", | ||
"adjust", | ||
"dim", | ||
"brighten", | ||
"lock", | ||
"unlock", | ||
]; | ||
return keywords.some(keyword => | ||
message.content.text.toLowerCase().includes(keyword) | ||
); | ||
}, | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
options: any, | ||
callback: HandlerCallback | ||
) => { | ||
const smartHomeManager = new SmartHomeManager(runtime); | ||
const result = await smartHomeManager.handleCommand(message.content.text, message.userId); | ||
|
||
const response: Content = { | ||
text: `Command executed: ${result.message || "Success"}`, | ||
action: "DEVICE_CONTROL_RESPONSE", | ||
source: "home-assistant" | ||
}; | ||
|
||
await callback(response); | ||
return response; | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Turn on the living room lights", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "I'll turn on the living room lights for you", | ||
action: "CONTROL_DEVICE", | ||
}, | ||
}, | ||
], | ||
] as ActionExample[][], | ||
} as Action; | ||
|
||
export async function controlDevice(deviceId: string, command: string, args: any = {}) { | ||
try { | ||
// Map internal commands to SmartThings commands | ||
const smartThingsCommand = mapCommand(command, args); | ||
|
||
await smartThingsApi.devices.executeCommand(deviceId, smartThingsCommand); | ||
|
||
// Update local device state | ||
await deviceStateProvider.updateDeviceState(deviceId, command, args); | ||
|
||
} catch (error) { | ||
console.error(`Failed to control device ${deviceId}:`, error); | ||
throw error; | ||
} | ||
} | ||
|
||
function mapCommand(command: string, args: any) { | ||
// Map our internal commands to SmartThings command format | ||
switch (command) { | ||
case 'turnOn': | ||
return { capability: 'switch', command: 'on' }; | ||
case 'turnOff': | ||
return { capability: 'switch', command: 'off' }; | ||
case 'setLevel': | ||
return { | ||
capability: 'switchLevel', | ||
command: 'setLevel', | ||
arguments: [args.level] | ||
}; | ||
// ... map other commands | ||
default: | ||
throw new Error(`Unknown command: ${command}`); | ||
} | ||
} | ||
|
||
export default controlDeviceAction; |
113 changes: 113 additions & 0 deletions
113
packages/client-eliza-home/src/actions/discover_devices.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { | ||
Action, | ||
ActionExample, | ||
Content, | ||
HandlerCallback, | ||
IAgentRuntime, | ||
Memory, | ||
State, | ||
} from "@elizaos/core"; | ||
import { EntityManager } from "../entities.ts"; | ||
import { CAPABILITIES } from '../capabilities'; | ||
import { smartThingsApi } from "../services/smart_things_api.ts"; | ||
|
||
export const discoverDevicesAction = { | ||
name: "DISCOVER_DEVICES", | ||
similes: ["SCAN_DEVICES", "FIND_DEVICES", "LIST_DEVICES"], | ||
description: "Discovers and lists all available smart home devices", | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
const keywords = [ | ||
"discover", | ||
"find", | ||
"scan", | ||
"list", | ||
"show", | ||
"what", | ||
"devices", | ||
"lights", | ||
"switches", | ||
]; | ||
return keywords.some(keyword => | ||
message.content.text.toLowerCase().includes(keyword) | ||
); | ||
}, | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State, | ||
options: any, | ||
callback: HandlerCallback | ||
) => { | ||
const entityManager = new EntityManager(runtime); | ||
await entityManager.discoverEntities(); | ||
|
||
const entities = entityManager.getAllEntities(); | ||
const deviceList = entities | ||
.map(entity => `- ${entity.name} (${entity.entityId}): ${entity.state}`) | ||
.join('\n'); | ||
|
||
const response: Content = { | ||
text: `Here are all the available devices:\n\n${deviceList}`, | ||
action: "DEVICE_LIST_RESPONSE", | ||
source: "home-assistant" | ||
}; | ||
|
||
await callback(response); | ||
return response; | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "What devices do you see?", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "Let me check what devices are available...", | ||
action: "DISCOVER_DEVICES", | ||
}, | ||
}, | ||
], | ||
] as ActionExample[][], | ||
} as Action; | ||
|
||
export default discoverDevicesAction; | ||
|
||
export async function discoverDevices() { | ||
// Implementation to discover SmartThings devices | ||
try { | ||
const devices = await smartThingsApi.devices.list(); | ||
|
||
return devices.map(device => ({ | ||
id: device.deviceId, | ||
name: device.label || device.name, | ||
capabilities: device.capabilities.map(cap => ({ | ||
id: cap.id, | ||
version: cap.version | ||
})), | ||
room: device.roomId, | ||
status: parseDeviceStatus(device.status) | ||
})); | ||
} catch (error) { | ||
console.error('Failed to discover devices:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
function parseDeviceStatus(status: any) { | ||
// Convert SmartThings status format to our internal format | ||
const deviceStatus: any = {}; | ||
|
||
if (status.switch) { | ||
deviceStatus.switch = status.switch.value; | ||
} | ||
if (status.level) { | ||
deviceStatus.level = status.level.value; | ||
} | ||
// ... parse other status values | ||
|
||
return deviceStatus; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { IAgentRuntime } from "@elizaos/core"; | ||
|
||
// Define SmartThings capability interfaces | ||
export interface SmartThingsCapability { | ||
id: string; | ||
version: number; | ||
} | ||
|
||
export const CAPABILITIES = { | ||
// Basic capabilities | ||
SWITCH: { id: 'switch', version: 1 }, | ||
POWER_METER: { id: 'powerMeter', version: 1 }, | ||
ENERGY_METER: { id: 'energyMeter', version: 1 }, | ||
|
||
// Climate capabilities | ||
THERMOSTAT: { id: 'thermostat', version: 1 }, | ||
TEMPERATURE_MEASUREMENT: { id: 'temperatureMeasurement', version: 1 }, | ||
HUMIDITY_MEASUREMENT: { id: 'humidityMeasurement', version: 1 }, | ||
|
||
// Lighting capabilities | ||
SWITCH_LEVEL: { id: 'switchLevel', version: 1 }, | ||
COLOR_CONTROL: { id: 'colorControl', version: 1 }, | ||
COLOR_TEMPERATURE: { id: 'colorTemperature', version: 1 }, | ||
|
||
// Security capabilities | ||
LOCK: { id: 'lock', version: 1 }, | ||
MOTION_SENSOR: { id: 'motionSensor', version: 1 }, | ||
CONTACT_SENSOR: { id: 'contactSensor', version: 1 }, | ||
PRESENCE_SENSOR: { id: 'presenceSensor', version: 1 }, | ||
|
||
// Media capabilities | ||
MEDIA_PLAYBACK: { id: 'mediaPlayback', version: 1 }, | ||
VOLUME: { id: 'volume', version: 1 }, | ||
|
||
// Window/Door capabilities | ||
WINDOW_SHADE: { id: 'windowShade', version: 1 }, | ||
GARAGE_DOOR: { id: 'garageDoor', version: 1 }, | ||
|
||
// Fan capabilities | ||
FAN_SPEED: { id: 'fanSpeed', version: 1 }, | ||
|
||
// Battery capabilities | ||
BATTERY: { id: 'battery', version: 1 }, | ||
} as const; | ||
|
||
export type CapabilityType = keyof typeof CAPABILITIES; | ||
|
||
export interface Capability { | ||
interface: string; | ||
version: string; | ||
type: string; | ||
properties: { | ||
supported: Array<{ | ||
name: string; | ||
}>; | ||
proactivelyReported: boolean; | ||
retrievable: boolean; | ||
}; | ||
} | ||
|
||
export class CapabilityManager { | ||
private runtime: IAgentRuntime; | ||
private capabilities: Map<string, Capability>; | ||
|
||
constructor(runtime: IAgentRuntime) { | ||
this.runtime = runtime; | ||
this.capabilities = new Map(); | ||
this.initializeCapabilities(); | ||
} | ||
|
||
private initializeCapabilities() { | ||
// Add standard capabilities | ||
this.addCapability({ | ||
interface: "Alexa.PowerController", | ||
version: "3", | ||
type: "AlexaInterface", | ||
properties: { | ||
supported: [{ name: "powerState" }], | ||
proactivelyReported: true, | ||
retrievable: true, | ||
}, | ||
}); | ||
|
||
this.addCapability({ | ||
interface: "Alexa.BrightnessController", | ||
version: "3", | ||
type: "AlexaInterface", | ||
properties: { | ||
supported: [{ name: "brightness" }], | ||
proactivelyReported: true, | ||
retrievable: true, | ||
}, | ||
}); | ||
|
||
// Add more capabilities as needed | ||
} | ||
|
||
addCapability(capability: Capability) { | ||
this.capabilities.set(capability.interface, capability); | ||
} | ||
|
||
getCapability(interfaceName: string): Capability | undefined { | ||
return this.capabilities.get(interfaceName); | ||
} | ||
|
||
getAllCapabilities(): Capability[] { | ||
return Array.from(this.capabilities.values()); | ||
} | ||
} |
Oops, something went wrong.