I’m creating a little project with the following set-up:
An external server monitors some sensors I installed on various stuff.
When a sensor is triggered, I want to launch a call on the FreePBX to a fixed number and when answered, playback a prerecorded message.
The dialplan part for this is not that hard, just check if the call gets answered or not.
But I’m not finding the solution to launch the dialplan via a HTTP message.
Although AMI has code that will allow you to do this via HTTP, that code is little used, and therefore not well maintained. You would be better off either creating a call file, or using the Originate action over the primary (TCP port 5038) AMI interface.
The best thing may be to set up an http server in the language of your choice. Copy a .call file to trigger the dialplan
Pseudo code example (untested) in node:
const http = require('http');
const fs = require('fs');
const src = /home/asterisk/alert.call
const dest = /var/spool/asterisk/outgoing/alert.call
// Define the port number to listen on
const port = 3000;
// Define the username and password for authentication
const auth = {
username: 'username',
password: 'password'
};
// Create the HTTP server
const server = http.createServer((req, res) => {
// Check if the request method is POST
if (req.method === 'POST') {
// Check if the authentication headers are present and correct
if (req.headers.authorization === `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString('base64')}`) {
// Read the contents of the .call file and write them to a new file
const fileCopy = fs.copyFile( src, dest)
fileCopy.on('finish', () => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('File copied successfully\n');
});
} else {
// Authentication failed
res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="Secure Area"' });
res.end('Unauthorized\n');
}
} else {
// Invalid request method
res.writeHead(405, { 'Allow': 'POST' });
res.end('Method Not Allowed\n');
}
});
// Start the server
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Although originates can be done with ARI, ARI wasn’t intended for cases where the ARI process is short running. Really the ARI process is a server, or at least has a coroutine relationship and should be running as long as Asterisk is running.
This Asterisk group thread on the relationship between AMI (etc.) stresses that ARI is not the new universal solution.
You never, ever copy a call file because it could be read partially before the copying is completed and triggered incompletely. You always move call files into the outgoing spool.
Also the move must not be across filesystems (as might happen if you created it on /tmp and then moved it to /var/spool (not sure if the FreePBX distribution creates this situation). Only moves within a filesystem are atomic, on Linux.
I don’t know how SNG7 sets things up, but /var/spool has to persist across reboots, but /tmp does not. As a result some systems may have /tmp on a tmpfs filesystem, as, for example, Debian does for /run and /run/lock. tmpfs space is taken from virtual memory, so uses RAM and swap file space.
It is also conceivable that someone would put one on spinning disks and the other on solid state “disk”, although I think that less likely.
One might want to exclude /tmp from RAID, for performance reasons, given that it won’t survive a reboot.
Thanks for all the input!
I created the following setup:
Created new user, with specific permissions (ssh, copy, move, chmod, chwon permissions).
Created a template callfile and put it in the user’s home dir.
Now I remotely start a script that copies and moves the file to /var/spool/asterisk/outgoing.