JavaLikeCalc.JavaScript
function hash(data, isName) {
	for(CRC = 0, i = 0; i < data.length; i++) {
		b = data.charCodeAt(i);
		for(j = 0; j < ((isName==true)?7:8); j++, b = b << 1)
			CRC = ((b^(CRC>>8)&0x80)?(CRC<<1)^0x8F57:CRC<<1) & 0xFFFF;
	}
	return CRC;
}

function nmHash(name) {
	for(srcF = name + "    ", hashF = "", iV = 0; iV < srcF.length; iV++) {
		tVl = srcF[iV]; tVl2 = srcF.charCodeAt(iV);
		if(tVl == "." && iV > 0)	{ hashF = hashF.slice(0,-1)+SYS.strFromCharCode(hashF.charCodeAt(hashF.length-1)+1); continue; }
		if(tVl2 >= 0x30 && tVl2 <= 0x39)		tVl = tVl2-0x30;
		else if(tVl2 >= 0x41 && tVl2 <= 0x5A)	tVl = tVl2-0x41+10;
		else if(tVl2 >= 0x61 && tVl2 <= 0x7A)	tVl = tVl2-0x61+10;
		else if(tVl == "-")	tVl = 10+26;
		else if(tVl == "_")	tVl = 10+26+1;
		else if(tVl == "/")	tVl = 10+26+2;
		else if(tVl == " ")	tVl = 10+26+3;
		else break;
		hashF += SYS.strFromCharCode(tVl*2);
	}
	if(iV < name.length || hashF.length < 4)	return -1;
	for(rez = "", iV = 0; iV < 4; iV++)
		rez += SYS.strFromCharCode(hashF.charCodeAt(iV)*2);

	//SYS.messDebug("/OWEN", "func="+name+"; code="+SYS.strDecode(rez));

	return hash(rez, true);
}

//Same request to the device
//  addr - negative for 11 bit type
function req(tr, addr, data) {
	if(addr < -2047 || addr > 255)	return "1:"+tr("Address out of the range [-2047...255].");
	req = SYS.strFromCharCode((addr>=0)?abs(addr):abs(addr)>>3, ((addr>=0)?0:abs(addr<<5))|((data.length>2)?data.length-2:0x10)) + data;

	// Appending CRC
	CRC = hash(req);
	req += SYS.strFromCharCode(CRC>>8, CRC&255);

	SYS.messDebug("/OWEN", "req="+SYS.strDecode(req));

	// Converting to ASCII
	for(reqASCII = "", i = 0; i < req.length; i++)
		reqASCII += SYS.strFromCharCode((req.charCodeAt(i)>>4)+71, (req.charCodeAt(i)&0x0F)+71);
	req = "#" + reqASCII + "\r";

	// Sending the request and getting response
	for(resp = tr.messIO(req); resp[resp.length-1] != "\r" && (respTail=tr.messIO("")).length; )
		resp += respTail;

	// Processing the response
	if(resp.length < req.length || resp[resp.length-1] != "\r" || resp[0] != "#" || (resp.length%2) != 0)
		return "10:"+tr("Wrong or no response.");

	//SYS.messDebug("/OWEN", "resp="+resp);

	resp = resp.slice(1, resp.length-1);

	// Converting to binary
	for(respBin = "", b = 0, i = 0, fullB = false; i < resp.length; i++, fullB = !fullB) {
		b += resp.charCodeAt(i) - 71;
		if(fullB) { respBin += SYS.strFromCharCode(b); b = 0; } else b *= 16;
	}
	resp = respBin;

	SYS.messDebug("/OWEN", "resp="+SYS.strDecode(resp));

	// Checking for CRC
	CRC = hash(resp.slice(0,-2));
	if(CRC != ((resp.charCodeAt(resp.length-2)<<8)+resp.charCodeAt(resp.length-1)))
		return "11:"+tr("Error CRC.");

	if(resp.charCodeAt(1) != (resp.length-6))
		return "12:"+tr("The data size is not equal to pointed one.");
	else if(resp.slice(2,4) != data.slice(0,2) && resp.charCodeAt(2,"UTF-16BE") != nmHash("n.Err"))
		return "21:Unpaired function in the response.";

	data = resp.slice(2, resp.length-2);
	//if(data.length < 3)	return "49:"+tr("Data size error.");

	return "0";
}

//Set transport and init
if(f_start) {
	dt = new Object();
	items_ = "";
	transport_ = transport;
	tr = SYS.Transport.nodeAt(transport,".");

	t_infW = ""; infWHoldTm = 0;
}
if(f_stop) return;

//Parsing the items to set and to create the user attributes
if(items != items_) {
	items_ = items;
	// Mark of checking to deletion needs
	for(var iDt in dt)	dt[iDt].mark = false;
	// Appending/Updating present ones
	for(itOff = 0; (sIt=items.parseLine(0,itOff)).length; ) {
		if(sIt[0] == "#")	continue;
		off1 = 0;
		itO = new Object();
		itO.addr = sIt.parse(0, ":", off1).toInt();
		itO.func = sIt.parse(0, ":", off1);
		itO.tp = sIt.parse(0, ":", off1);
		itO.md = sIt.parse(0, ":", off1);
		itO.id = sIt.parse(0, ":", off1);
		itO.nm = sIt.slice(off1);
		if(!itO.nm.length)	itO.nm = itO.id.length ? itO.id : itO.func;
		if(!itO.id.length)	itO.id = itO.func.replace(new RegExp("[.]"), "_");
		SYS.messDebug("/OWEN", "id="+itO.id);
		if(itO.tp == "u" || itO.tp == "i") {
			wTp = "integer";
			itO.sz = itO.tp.slice(1).toInt();
			itO.sz = (itO.sz?itO.sz:16)/8;
			if(!(itO.sz==1||itO.sz==2||itO.sz==4))	continue; 
		}
		else if(itO.tp == "s")	wTp = "string";
		else if(itO.tp == "f")	wTp = "real";
		else continue;
		itO.rd = (itO.md.indexOf("r") >= 0); itO.wr = (itO.md.indexOf("w") >= 0);
		if(!itO.wr)	wTp += "|ro";
		if((itO.funcH=nmHash(itO.func)) < 0)	continue;
		// Apending
		dt[itO.id] = itO;
		if(itO.rd || itO.wr) {
			this.attrAdd(itO.id, itO.nm, wTp);
			if(itO.wr)	itO.val = this[itO.id].get();
			itO.mark = true;
			//SYS.messDebug("/OWEN", "itO="+itO.id+"; tmpAddr="+tmpAddr+"; addr="+itO.addr);
		}
	}
	// Check, remove item and set to EVAL the attribute
	for(var iDt in dt) {
		if(dt[iDt].mark)	continue;
		this[dt[iDt].id].set(EVAL, 0, 0, true);	//If the attribute locked
		this.attrDel(dt[iDt].id);
		delete dt[iDt];
	}
}

t_err = "0";

//Check for the transport change and connect
if(!tr || transport != transport_)	{
	transport_ = transport;
	tr = SYS.Transport.nodeAt(transport,".");
}
if(!tr)	t_err = "1:"+tr("Error the output transport '%1'.").replace("%1",transport);
else {
	t_inf = "";
	if(infWHoldTm && SYS.time() > infWHoldTm)	t_infW = "", infWHoldTm = 0;
	
	//The parameters processing
	for(var iDt in dt) {
		itO = dt[iDt];
		if(!t_err.toInt()) {
			SYS.messDebug("/OWEN", "iDt="+iDt);

			// Writing
			if(itO.wr && !(tVl=this[itO.id].get()).isEVal() && tVl != itO.val) {
				data = SYS.strFromCharCode(itO.funcH>>8, itO.funcH&0xFF);
				if(itO.tp == "f") {
					tVl2 = tVl3 = 0;
					Special.FLibSYS.floatSplitWord(tVl, tVl2, tVl3);
					data += SYS.strFromCharCode(tVl3>>8, tVl3&0xFF, tVl2>>8) + ((tVl2&0xFF)?SYS.strFromCharCode(tVl2&0xFF):"");
				}
				else if(itO.tp == "u" || itO.tp == "i") {
					for(tVl2 = SYS.strFromCharCode(tVl&0xFF), tVl = tVl>>8; tVl; tVl = tVl>>8)
						tVl2 = SYS.strFromCharCode(tVl&0xFF) + tVl2;
					data += tVl2;
				}
				else if(itO.tp == "s")
					for(iV = tVl.length-1; iV >= 0; iV--)	data += tVl[iV];

				if(!(t_err=req(tr,itO.addr,data)).toInt()) {
					if(data.charCodeAt(0,"UTF-16BE") == nmHash("n.Err")) {
						t_infW += (t_infW.length?"; ":": ")+itO.nm+":nErr=0x"+data.charCodeAt(2).toString(16);
						infWHoldTm = SYS.time()+10;
					} else itO.val = tVl;
				}
			}

			// Reading
			data = SYS.strFromCharCode(itO.funcH>>8, itO.funcH&0xFF);
			if(itO.rd && !(t_err=req(tr,itO.addr,data)).toInt()) {
				if(data.charCodeAt(0,"UTF-16BE") == nmHash("n.Err") && itO.funcH != nmHash("n.Err")) {
					t_inf += (t_inf.length?"; ":": ")+itO.nm+":nErr=0x"+data.charCodeAt(2).toString(16);
					this[itO.id].set(EVAL, 0, 0, true); itO.val = EVAL;
				}
				else {
					data = data.slice(2);
					if(itO.tp == "f") {
						if(data.length == 1)
							tVl = EVAL, t_inf += (t_inf.length?"; ":": ")+itO.nm+":err=0x"+data.charCodeAt(0).toString(16);
						else if(data.length >= 3)
							tVl = Special.FLibSYS.floatMergeWord(
								data.charCodeAt(2)*256+((data.length < 4)?0:data.charCodeAt(3)),
								data.charCodeAt(0)*256+data.charCodeAt(1));
						else tVl = EVAL;
						this[itO.id].set(tVl, 0, 0, true); itO.val = tVl;
					}
					else if(itO.tp == "u" || itO.tp == "i") {
						for(tVl = 0, iV = 0; iV < data.length; iV++)
							tVl = (tVl<<8) | data.charCodeAt(iV);
						this[itO.id].set(tVl, 0, 0, true); itO.val = tVl;
						//SYS.messDebug("/OWEN", "Integer data="+SYS.strDecode(data)+"; Sz="+itO.sz);
					}
					else if(itO.tp == "s")	{
						for(tVl = "", iV = 0; iV < data.length; iV++)	tVl = data[iV] + tVl;
						this[itO.id].set(tVl, 0, 0, true);	 itO.val = tVl;
					}
					continue;
				}
			}
		}
		this[itO.id].set(EVAL, 0, 0, true); itO.val = EVAL;
	}
}

f_err = t_err;
if(!f_err.toInt())	f_err += t_inf + (t_infW.length?" "+tr("Write")+t_infW:"");