<commit_before>var appConf = require("./config/app.json");
var astConf = require("./config/asterisk.json");
var amiConf = astConf.ami;

var myLib = require("./myLib");
var engineApi = require("./engineApi");
var s = require("./localStorage");

var ami = new require('asterisk-manager')(amiConf.port, amiConf.host, amiConf.username, amiConf.password, true);
// https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+AMI+Events
// https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+AMI+Actions
ami.keepConnected();

	s.asterisk = {
		sms_out: {}, // map for storing pending outgoing sms
		sms_in: new Map(), // map for storing multipart incoming sms
		channels: {},
		conference: {
//			input: null,
//			output: null,
	//		members: {},
			on_air: null
		},
		master: {
		}
	};


var eventCallbacks = {
	'initialized': function () {}
};

exports.on = function (event, callback) {
	if (eventCallbacks.hasOwnProperty(event) && 'function' === typeof callback) {
		eventCallbacks[event] = callback;
	} else {
		myLib.consoleLog('panic', 'ami::eventCallbacks', [event, callback]);
	}
};


// start initialization sequence
// this code is executed when our app (re)connects to Asterisk
ami.on('fullybooted', function(evt) {
	myLib.consoleLog('log', "init", "Asterisk interface ready!");
	//clear previous channel properties
	s.ui.mixer.channels = {};
	s.asterisk.channels = {};

	if (astConf.dongles && Object.keys(astConf.dongles).length > 0) {
		// we want all configured dongle channels to be present
		for (var dongleName in astConf.dongles) {
			//s.ui.mixer.channels[dongleName] = mixerLib.createChannel('dongle', astConf.dongles[dongleName].number);
			engineApi.channelUpdate(dongleName, {
				type: 'dongle',
				label: astConf.dongles[dongleName].label
			});
			s.asterisk.channels[dongleName] = {};
		}

		//clear previous dongle update job
		if (s.asterisk.dongleInfoUpdate) {
			clearInterval(s.asterisk.dongleInfoUpdate);
			s.asterisk.dongleInfoUpdate = null;
		}

		ami.action({
			action: "DongleShowDevices"
		}, function(err, res) {
			//{"response":"Success","actionid":"1446811737040","eventlist":"start","message":"Device status list will follow"}
			if (!err && res.response === 'Success') { // 'dongledeviceentry' events will follow, ends with 'DongleShowDevicesComplete'
				myLib.consoleLog('log', "init", 'Dongle driver is talking');
				if (astConf.DongleInfoInterval) {
					s.asterisk.dongleInfoUpdate = setInterval(function() {
						ami.action({ action: "DongleShowDevices" });
					}, astConf.DongleInfoInterval * 1000);
				}
			} else {
				myLib.consoleLog('error', 'init Dongle', JSON.stringify(err) + " " + JSON.stringify(res));
			}
		});
	}

	ami.action({ // list SIP and other relevant peers present at time of connection
		action: "DeviceStateList"
	}, function(err, res) {  // 'DeviceStateChange' events will follow, ends with 'DeviceStateListComplete'
		// this must succeed
	});
});

// shoud happen only on init
ami.on('devicestatelistcomplete', function(evt) {
	ami.action({ // list active channels at time of connection
		action: "CoreShowChannels"
	}, function(err, res) { // 'coreshowchannel' events will follow, ends with 'CoreShowChannelsComplete'
		// this must succeed
	});

	ami.action({
		action: "ConfbridgeList",
		conference: astConf.virtual.master.split('@')[0]
	}, function(err, res) {
		// { response: 'Success', actionid: '1447157967259', eventlist: 'start', message: 'Confbridge user list will follow' }
		if (!err && res.response === 'Success') { // 'confbridgelist' events will follow
			myLib.consoleLog('debug', "ConfbridgeList", res);
		} else {
			myLib.consoleLog('error', "ConfbridgeList", JSON.stringify(res));
			if (astConf.console && (astConf.console.in || astConf.console.out)) {
				ami.action({
//					action: "ModuleCheck",
//					module: 'chan_alsa'
					action: "Command",
					command: 'core show channeltype console'
				}, function(err, res) {
					myLib.consoleLog('debug', "ModuleCheck", [err, res]);
					if (err) {
						myLib.consoleLog('error', "ModuleCheck", err);
						s.ui.mixer.master.in = null;
						s.ui.mixer.master.out = null;
					}
					eventCallbacks.initialized();
				});
			}
		}
	});
});

ami.on('dongledeviceentry', function(evt) {
//	{"event":"dongledeviceentry","actionid":"1446811737040","device":"airtel1","audiosetting":"","datasetting":"","imeisetting":"354369047238739","imsisetting":"","channellanguage":"mk","context":"from-trunk","exten":"+1234567890","group":"0","rxgain":"4","txgain":"1","u2diag":"0","usecallingpres":"yes","defaultcallingpres":"presentation allowed, passed screen","autodeletesms":"yes","disablesms":"no","resetdongle":"yes","smspdu":"yes","callwaitingsetting":"disabled","dtmf":"relax","minimaldtmfgap":"45","minimaldtmfduration":"80","minimaldtmfinterval":"200","state":"free","audiostate":"/dev/ttyusb4","datastate":"/dev/ttyusb5","voice":"yes","sms":"yes","manufacturer":"huawei","model":"e1731","firmware":"11.126.16.04.284","imeistate":"354369047238739","imsistate":"640050939309334","gsmregistrationstatus":"registered, home network","rssi":"11, -91 dbm","mode":"wcdma","submode":"wcdma","providername":"celtel","locationareacode":"50","cellid":"bbe887e","subscribernumber":"+255689514544","smsservicecenter":"+255780000004","useucs2encoding":"yes","ussduse7bitencoding":"no","ussduseucs2decoding":"yes","tasksinqueue":"0","commandsinqueue":"0","callwaitingstate":"disabled","currentdevicestate":"start","desireddevicestate":"start","callschannels":"0","active":"0","held":"0","dialing":"0","alerting":"0","incoming":"0","waiting":"0","releasing":"0","initializing":"0"}<commit_msg>Start properly when console channel not configured<commit_after>var appConf = require("./config/app.json");
var astConf = require("./config/asterisk.json");
var amiConf = astConf.ami;

var myLib = require("./myLib");
var engineApi = require("./engineApi");
var s = require("./localStorage");

var ami = new require('asterisk-manager')(amiConf.port, amiConf.host, amiConf.username, amiConf.password, true);
// https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+AMI+Events
// https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+AMI+Actions
ami.keepConnected();

	s.asterisk = {
		sms_out: {}, // map for storing pending outgoing sms
		sms_in: new Map(), // map for storing multipart incoming sms
		channels: {},
		conference: {
//			input: null,
//			output: null,
	//		members: {},
			on_air: null
		},
		master: {
		}
	};


var eventCallbacks = {
	'initialized': function () {}
};

exports.on = function (event, callback) {
	if (eventCallbacks.hasOwnProperty(event) && 'function' === typeof callback) {
		eventCallbacks[event] = callback;
	} else {
		myLib.consoleLog('panic', 'ami::eventCallbacks', [event, callback]);
	}
};


// start initialization sequence
// this code is executed when our app (re)connects to Asterisk
ami.on('fullybooted', function(evt) {
	myLib.consoleLog('log', "init", "Asterisk interface ready!");
	//clear previous channel properties
	s.ui.mixer.channels = {};
	s.asterisk.channels = {};

	if (astConf.dongles && Object.keys(astConf.dongles).length > 0) {
		// we want all configured dongle channels to be present
		for (var dongleName in astConf.dongles) {
			//s.ui.mixer.channels[dongleName] = mixerLib.createChannel('dongle', astConf.dongles[dongleName].number);
			engineApi.channelUpdate(dongleName, {
				type: 'dongle',
				label: astConf.dongles[dongleName].label
			});
			s.asterisk.channels[dongleName] = {};
		}

		//clear previous dongle update job
		if (s.asterisk.dongleInfoUpdate) {
			clearInterval(s.asterisk.dongleInfoUpdate);
			s.asterisk.dongleInfoUpdate = null;
		}

		ami.action({
			action: "DongleShowDevices"
		}, function(err, res) {
			//{"response":"Success","actionid":"1446811737040","eventlist":"start","message":"Device status list will follow"}
			if (!err && res.response === 'Success') { // 'dongledeviceentry' events will follow, ends with 'DongleShowDevicesComplete'
				myLib.consoleLog('log', "init", 'Dongle driver is talking');
				if (astConf.DongleInfoInterval) {
					s.asterisk.dongleInfoUpdate = setInterval(function() {
						ami.action({ action: "DongleShowDevices" });
					}, astConf.DongleInfoInterval * 1000);
				}
			} else {
				myLib.consoleLog('error', 'init Dongle', JSON.stringify(err) + " " + JSON.stringify(res));
			}
		});
	}

	ami.action({ // list SIP and other relevant peers present at time of connection
		action: "DeviceStateList"
	}, function(err, res) {  // 'DeviceStateChange' events will follow, ends with 'DeviceStateListComplete'
		// this must succeed
	});
});

// shoud happen only on init
ami.on('devicestatelistcomplete', function(evt) {
	ami.action({ // list active channels at time of connection
		action: "CoreShowChannels"
	}, function(err, res) { // 'coreshowchannel' events will follow, ends with 'CoreShowChannelsComplete'
		// this must succeed
	});

	ami.action({
		action: "ConfbridgeList",
		conference: astConf.virtual.master.split('@')[0]
	}, function(err, res) {
		// { response: 'Success', actionid: '1447157967259', eventlist: 'start', message: 'Confbridge user list will follow' }
		if (!err && res.response === 'Success') { // 'confbridgelist' events will follow
			myLib.consoleLog('debug', "ConfbridgeList", res);
		} else {
			myLib.consoleLog('error', "ConfbridgeList", JSON.stringify(res));
			if (astConf.console && (astConf.console.in || astConf.console.out)) {
				ami.action({
//					action: "ModuleCheck",
//					module: 'chan_alsa'
					action: "Command",
					command: 'core show channeltype console'
				}, function(err, res) {
					myLib.consoleLog('debug', "ModuleCheck", [err, res]);
					if (err) {
						myLib.consoleLog('error', "ModuleCheck", err);
						s.ui.mixer.master.in = null;
						s.ui.mixer.master.out = null;
					}
					eventCallbacks.initialized();
				});
			} else {
				myLib.consoleLog('warning', "console channel disabled", "audio input/output will not work");
				eventCallbacks.initialized();
			}
		}
	});
});

ami.on('dongledeviceentry', function(evt) {
//	{"event":"dongledeviceentry","actionid":"1446811737040","device":"airtel1","audiosetting":"","datasetting":"","imeisetting":"354369047238739","imsisetting":"","channellanguage":"mk","context":"from-trunk","exten":"+1234567890","group":"0","rxgain":"4","txgain":"1","u2diag":"0","usecallingpres":"yes","defaultcallingpres":"presentation allowed, passed screen","autodeletesms":"yes","disablesms":"no","resetdongle":"yes","smspdu":"yes","callwaitingsetting":"disabled","dtmf":"relax","minimaldtmfgap":"45","minimaldtmfduration":"80","minimaldtmfinterval":"200","state":"free","audiostate":"/dev/ttyusb4","datastate":"/dev/ttyusb5","voice":"yes","sms":"yes","manufacturer":"huawei","model":"e1731","firmware":"11.126.16.04.284","imeistate":"354369047238739","imsistate":"640050939309334","gsmregistrationstatus":"registered, home network","rssi":"11, -91 dbm","mode":"wcdma","submode":"wcdma","providername":"celtel","locationareacode":"50","cellid":"bbe887e","subscribernumber":"+255689514544","smsservicecenter":"+255780000004","useucs2encoding":"yes","ussduse7bitencoding":"no","ussduseucs2decoding":"yes","tasksinqueue":"0","commandsinqueue":"0","callwaitingstate":"disabled","currentdevicestate":"start","desireddevicestate":"start","callschannels":"0","active":"0","held":"0","dialing":"0","alerting":"0","incoming":"0","waiting":"0","releasing":"0","initializing":"0"}
{'fraction_non_alphanumeric': 0.19028871391076116, 'fraction_numerical': 0.03184601924759405, 'mean_word_length': 5.4728199320498305, 'pattern_counts': {'":': 130, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1123314', 'n_tokens_mistral': 4308, 'n_tokens_neox': 3726, 'n_words': 640}