JavaLikeCalc.JavaScript
//Request form:
//<{cmd} pin="1111" tel="+380XXXXXXXXX" text="{0|1}" err="1:Error">{SMSText}</cmd>
//  cmd - command, for now only "send" allowed;
//  pin - PIN code to the SIM card access;
//  tel - telephone number for receiver (remote cell phone or GSM modem);
//  text{0,1} - SMS in the text mode, only ASCII
//  SMSText - the message text;
//  err - sets for the request result.

//Transport's timings check
if(tr.timings() != "5000:100")	tr.timings("5000:100");

if(io.name() == "send") {
	tel = io.attr("tel");
	if(!tel.length || tel[0] != "+") { io.setAttr("err", "100:"+tr("Telephone number error.")); return; }

	//Disable ECHO
	rez = tr.messIO("ATE0\r");
	while(rez.length && (trez=tr.messIO("")).length) rez += trez;
	if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "101:"+tr("Error disabling ECHO: %1").replace("%1",rez)); return; }

	//Set PIN
	if(io.attr("pin").length) {
		//Check for PIN
		rez = tr.messIO("AT+CPIN?\r");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "102:"+tr("Error checking for PIN-code: %1").replace("%1",rez)); return; }
		if(rez.indexOf("+CPIN: READY\r") < 0) {	//PIN is needed
			rez = tr.messIO("AT+CPIN="+io.attr("pin")+"\r");
			while(rez.length && (trez=tr.messIO("")).length) rez += trez;
			if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "102:"+tr("Error setting PIN: %1").replace("%1",rez)); return; }
		}
	}

	if(io.attr("text").toInt()) {	//SMS in the text mode
		//Switch to Text SMS mode
		rez = tr.messIO("AT+CMGF=1\r");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "103:"+tr("Error setting the SMS Text mode: %1").replace("%1",rez)); return; }

		//Send the Telephone number
		rez = tr.messIO("AT+CMGS=\""+tel+"\"\r");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		if(rez.indexOf(">") < 0)	{ io.setAttr("err", "104:"+tr("Error sending SMS: %1").replace("%1",rez)); return; }
		rez = tr.messIO(io.text()+"\x1A");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		//for(var iTr = 0; iTr < 100 && rez.indexOf("OK\r") < 0; iTr++) rez += tr.messIO("");	//Up to 10 seconds wait for reply
		if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "104:"+tr("Error sending SMS PDU: %1").replace("%1",rez)); return; }
	}
	else {	//SMS in the PDU mode
		// Switch to PDU SMS mode
		rez = tr.messIO("AT+CMGF=0\r");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "103:"+tr("Error setting the SMS PDU mode: %1").replace("%1",rez)); return; }

		//Prepare PDU
		pdu = "001100";	//SMS center number (default) + SMS-Submit
		//Telephone number encode
		tel = tel.slice(1);
		pdu += tel.length.toString(16,2) + "91";	//Telephone length and type
		while(tel.length < 12) tel += "F";
		for(i = 0; i < 6; i++) pdu += tel[i*2+1]+tel[i*2];
		//Message encode
		text = SYS.strCodeConv(io.text(),"","UCS2");
		if((text.length/2) > 70)	text = text.slice(0,140);
		//{ io.setAttr("err", "104:"+tr("Too long length (%1) of the message.").replace("%1",(text.length/2).toString())); return; }
		pdu += "0018C1"+(text.length).toString(16,2);
		for(i = 0; i < text.length/2; i++) pdu += text.charCodeAt(i*2+1).toString(16,2)+text.charCodeAt(i*2).toString(16,2);
		//SYS.messDebug("TEST SMS","PDU :"+pdu);

		// Send the PDU message
		rez = tr.messIO("AT+CMGS="+(pdu.length/2-1)+"\r");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		if(rez.indexOf(">") < 0)	{ io.setAttr("err", "104:"+tr("Error sending SMS: %1").replace("%1",rez)); return; }
		rez = tr.messIO(pdu+"\x1A");
		while(rez.length && (trez=tr.messIO("")).length) rez += trez;
		//for(var iTr = 0; iTr < 100 && rez.indexOf("OK\r") < 0; iTr++) rez += tr.messIO("");	//Up to 10 seconds wait for reply
		if(rez.indexOf("OK\r") < 0)	{ io.setAttr("err", "104:"+tr("Error sending SMS PDU: %1").replace("%1",rez)); return; }
		//SYS.messDebug("TEST SMS","PDU REZ :"+rez);
	}
	io.setAttr("err", "0");
}