Updated the code further to add the pin functionality for voice mode.
// discovery.js
// Lambda function to handle Alexa.Discovery directives for the GDO Blaq Garage Opener
const { v4: uuidv4 } = require('uuid');
/**
* Builds the Discover.Response for the GDO Blaq Garage Opener device.
*/
function buildDiscoveryResponse() {
return {
event: {
header: {
namespace: 'Alexa.Discovery',
name: 'Discover.Response',
payloadVersion: '3',
messageId: uuidv4(),
},
payload: {
endpoints: [
{
endpointId: 'gdo-blaq-001',
manufacturerName: 'Konnected',
friendlyName: 'GDO Blaq Garage Opener',
description: 'Konnected GDO Blaq Garage Opener',
displayCategories: ['GARAGE_DOOR'],
cookie: {},
capabilities: [
{
type: 'AlexaInterface',
interface: 'Alexa.Discovery',
version: '3'
},
{
// Voice control with PIN: ModeController for open/close
type: 'AlexaInterface',
interface: 'Alexa.ModeController',
instance: 'Door.VoiceMode',
version: '3',
properties: {
supported: [{ name: 'mode' }],
proactivelyReported: true,
retrievable: true
},
configuration: {
ordered: false,
supportedModes: [
{
value: { mode: 'OPEN' },
modeResources: {
friendlyNames: [
{ value: { text: 'Open', locale: 'en-US' } }
]
}
},
{
value: { mode: 'CLOSED' },
modeResources: {
friendlyNames: [
{ value: { text: 'Closed', locale: 'en-US' } }
]
}
}
]
},
semantics: {
actionMappings: [
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Open'],
directive: { name: 'SetMode', value: { mode: 'OPEN' } }
},
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Close'],
directive: { name: 'SetMode', value: { mode: 'CLOSED' } }
}
],
stateMappings: [
{
"@type": 'StatesToValue',
states: ['Alexa.States.Open'],
value: { mode: 'OPEN' }
},
{
"@type": 'StatesToValue',
states: ['Alexa.States.Closed'],
value: { mode: 'CLOSED' }
}
]
}
},
{
// Primary widget: tap card to toggle open/close (UI only)
type: 'AlexaInterface',
interface: 'Alexa.PowerController',
version: '3',
properties: {
supported: [{ name: 'powerState' }],
proactivelyReported: true,
retrievable: true
},
semantics: {
actionMappings: [
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Open'],
directive: { name: 'TurnOn' }
},
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Close'],
directive: { name: 'TurnOff' }
}
],
stateMappings: [
{
"@type": 'StatesToValue',
states: ['Alexa.States.Open'],
value: { powerState: 'ON' }
},
{
"@type": 'StatesToValue',
states: ['Alexa.States.Closed'],
value: { powerState: 'OFF' }
}
]
}
},
{
// Detail view: slider for setting door position (0–100%)
type: 'AlexaInterface',
interface: 'Alexa.RangeController',
instance: 'Door.Position',
version: '3',
properties: {
supported: [{ name: 'rangeValue' }],
proactivelyReported: true,
retrievable: true
},
configuration: {
supportedRange: { minimumValue: 0, maximumValue: 100, precision: 1 },
unitOfMeasure: 'PERCENT'
},
semantics: {
actionMappings: [
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Open', 'Alexa.Actions.Increase'],
directive: { name: 'SetRangeValue', value: { rangeValue: 100 } }
},
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Close', 'Alexa.Actions.Decrease'],
directive: { name: 'SetRangeValue', value: { rangeValue: 0 } }
}
],
stateMappings: [
{
"@type": 'StatesToValue',
states: ['Alexa.States.Open'],
value: { rangeValue: 100 }
},
{
"@type": 'StatesToValue',
states: ['Alexa.States.Closed'],
value: { rangeValue: 0 }
}
]
}
},
{
// Detail view: lock/unlock button
type: 'AlexaInterface',
interface: 'Alexa.LockController',
version: '3',
properties: {
supported: [{ name: 'lockState' }],
proactivelyReported: true,
retrievable: true
}
},
{
// Detail view: online/offline connectivity indicator
type: 'AlexaInterface',
interface: 'Alexa.EndpointHealth',
version: '3',
properties: {
supported: [{ name: 'connectivity' }],
proactivelyReported: true,
retrievable: true
}
},
{
// Settings: enable or disable voice open/close
type: 'AlexaInterface',
interface: 'Alexa.ModeController',
instance: 'Door.VoiceSetting',
version: '3',
properties: {
supported: [{ name: 'mode' }],
proactivelyReported: true,
retrievable: true
},
configuration: {
ordered: false,
supportedModes: [
{
value: { mode: 'ENABLED' },
modeResources: {
friendlyNames: [
{ value: { text: 'Voice Enabled', locale: 'en-US' } }
]
}
},
{
value: { mode: 'DISABLED' },
modeResources: {
friendlyNames: [
{ value: { text: 'Voice Disabled', locale: 'en-US' } }
]
}
}
]
},
semantics: {
actionMappings: [
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Enable'],
directive: { name: 'SetMode', value: { mode: 'ENABLED' } }
},
{
"@type": 'ActionsToDirective',
actions: ['Alexa.Actions.Disable'],
directive: { name: 'SetMode', value: { mode: 'DISABLED' } }
}
],
stateMappings: [
{
"@type": 'StatesToValue',
states: ['Alexa.States.Enabled'],
value: { mode: 'ENABLED' }
},
{
"@type": 'StatesToValue',
states: ['Alexa.States.Disabled'],
value: { mode: 'DISABLED' }
}
]
}
}
]
}
]
}
}
};
}
/**
* Main Lambda handler
*/
exports.handler = async (event) => {
const { directive } = event;
const { header } = directive;
// Handle Discovery request
if (header.namespace === 'Alexa.Discovery' && header.name === 'Discover') {
return buildDiscoveryResponse();
}
// If not handled, throw an error
throw new Error(`Unsupported directive: ${header.namespace}.${header.name}`);
};