package mods.eln.sixnode.modbusrtu; import mods.eln.Eln; import mods.eln.i18n.I18N; import mods.eln.misc.Direction; import mods.eln.misc.LRDU; import mods.eln.misc.Utils; import mods.eln.node.NodeBase; import mods.eln.node.six.SixNode; import mods.eln.node.six.SixNodeDescriptor; import mods.eln.node.six.SixNodeElement; import mods.eln.sim.ElectricalLoad; import mods.eln.sim.IProcess; import mods.eln.sim.ThermalLoad; import mods.eln.sim.nbt.NbtElectricalGateInputOutput; import mods.eln.sim.nbt.NbtElectricalGateOutputProcess; import mods.eln.sixnode.wirelesssignal.IWirelessSignalSpot; import mods.eln.sixnode.wirelesssignal.IWirelessSignalTx; import mods.eln.sixnode.wirelesssignal.WirelessUtils; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; public class ModbusRtuElement extends SixNodeElement implements IModbusSlave { public NbtElectricalGateInputOutput[] ioGate = new NbtElectricalGateInputOutput[4]; public NbtElectricalGateOutputProcess[] ioGateProcess = new NbtElectricalGateOutputProcess[4]; HashMap<Integer, ServerWirelessTxStatus> wirelessTxStatusList = new HashMap<Integer, ServerWirelessTxStatus>(); HashMap<Integer, ServerWirelessRxStatus> wirelessRxStatusList = new HashMap<Integer, ServerWirelessRxStatus>(); ModbusRtuDescriptor descriptor; static final int ioStartOffset = 16; static final int ioRange = 8; int station = -1; String name = ""; HashMap<String, HashSet<IWirelessSignalTx>> txSet = new HashMap<String, HashSet<IWirelessSignalTx>>(); HashMap<IWirelessSignalTx, Double> txStrength = new HashMap<IWirelessSignalTx, Double>(); static final byte setStation = 1; static final byte setName = 2; static final byte serverTxAdd = 3; static final byte serverRxAdd = 4; static final byte serverTxConfig = 5; static final byte serverRxConfig = 6; static final byte serverTxDelete = 7; static final byte serverRxDelete = 8; static final byte serverAllSyncronise = 9; static final byte clientAllSyncronise = 1; static final byte clientTx1Syncronise = 2; static final byte clientRx1Syncronise = 3; static final byte clientTxDelete = 4; static final byte clientRxDelete = 5; static final byte clientRx1Connected = 6; static final byte ClientModbusActivityEvent = 7; static final byte ClientModbusErrorEvent = 8; boolean addedOnServer = false; ArrayList<IModbusSlot> mapping = new ArrayList<IModbusSlot>(); ModbusNullSlot nullSlot = new ModbusNullSlot(); public ModbusRtuElement(SixNode sixNode, Direction side, SixNodeDescriptor descriptor) { super(sixNode, side, descriptor); for (int idx = 0; idx < 4; idx++) { ioGate[idx] = new NbtElectricalGateInputOutput("ioGate" + idx); ioGateProcess[idx] = new NbtElectricalGateOutputProcess("ioGateProcess" + idx, ioGate[idx]); electricalLoadList.add(ioGate[idx]); electricalComponentList.add(ioGateProcess[idx]); ioGateProcess[idx].setHighImpedance(true); mapping.add(new modbusAnalogIoSlot(ioStartOffset + idx * ioRange, ioRange, ioGate[idx], ioGateProcess[idx])); } slowProcessList.add(new ModbusRtuSlowProcess()); this.descriptor = (ModbusRtuDescriptor) descriptor; } class ModbusRtuSlowProcess implements IProcess { double sleepTimer = 0; @Override public void process(double time) { sleepTimer -= time; if (sleepTimer < 0) { sleepTimer += Utils.rand(1.2, 2); IWirelessSignalSpot spot = WirelessUtils.buildSpot(getCoordonate(), null, 0); WirelessUtils.getTx(spot, txSet, txStrength); } for (ServerWirelessRxStatus rx : wirelessRxStatusList.values()) { if (rx.isConnected() != rx.connected) { rx.connected = !rx.connected; sendRx1Connected(rx); } } } } @Override public ElectricalLoad getElectricalLoad(LRDU lrdu) { return ioGate[lrdu.toInt()]; } @Override public ThermalLoad getThermalLoad(LRDU lrdu) { return null; } @Override public int getConnectionMask(LRDU lrdu) { return NodeBase.maskElectricalGate; } @Override public String multiMeterString() { return null; // Utils.plotUIP(powerLoad.Uc, powerLoad.getCurrent()); } @Nullable @Override public Map<String, String> getWaila() { Map<String, String> info = new HashMap<String, String>(); if (Eln.modbusEnable) { info.put(I18N.tr("Modbus TCP"), Eln.modbusServer.getHost() + ":" + Eln.modbusServer.getPort()); info.put(I18N.tr("Modbus Unit ID"), String.valueOf(station)); } else { info.put("X_X", I18N.tr("Modbus is disabled, enable it in Eln.cfg")); } return info; } @Override public String thermoMeterString() { return null; } @Override public void initialize() { addToServer(); // connect(); } @Override public void destroy(EntityPlayerMP entityPlayer) { super.destroy(entityPlayer); unregister(); } @Override public void unload() { super.unload(); unregister(); } void unregister() { removeFromServer(); // Remove all TX signals. for (Integer key : wirelessTxStatusList.keySet()) { ServerWirelessTxStatus status = wirelessTxStatusList.get(key); status.delete(); wirelessTxStatusList.remove(key); } } @Override public boolean onBlockActivated(EntityPlayer entityPlayer, Direction side, float vx, float vy, float vz) { if (Utils.isPlayerUsingWrench(entityPlayer)) { if (side.isY()) { front = front.getNextClockwise(); sixNode.reconnect(); sixNode.setNeedPublish(true); } return true; } else { return false; } } @Override public void networkSerialize(DataOutputStream stream) { super.networkSerialize(stream); try { stream.writeInt(station); stream.writeUTF(name); } catch (IOException e) { e.printStackTrace(); } } void sendTx1Syncronise(WirelessTxStatus tx) { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); try { packet.writeByte(clientTx1Syncronise); tx.writeTo(packet); } catch (IOException e) { e.printStackTrace(); } // TODO sendPacketToAllClient(bos); } void sendRx1Syncronise(WirelessRxStatus rx) { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); try { packet.writeByte(clientRx1Syncronise); rx.writeTo(packet); } catch (IOException e) { e.printStackTrace(); } // TODO sendPacketToAllClient(bos); } void sendRx1Connected(WirelessRxStatus rx) { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); try { packet.writeByte(clientRx1Connected); packet.writeInt(rx.uuid); packet.writeBoolean(rx.connected); } catch (IOException e) { e.printStackTrace(); } // TODO sendPacketToAllClient(bos); } void onActivity() { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); try { packet.writeByte(ClientModbusActivityEvent); } catch (IOException e) { e.printStackTrace(); } sendPacketToAllClient(bos); } void onError() { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); try { packet.writeByte(ClientModbusErrorEvent); } catch (IOException e) { e.printStackTrace(); } sendPacketToAllClient(bos); } @Override public void networkUnserialize(DataInputStream stream, EntityPlayerMP player) { super.networkUnserialize(stream, player); try { switch (stream.readByte()) { case setStation: setStation(stream.readInt()); break; case setName: setName(stream.readUTF()); break; case serverTxAdd: { int idx = 0; String name = stream.readUTF(); int uuid = 0; /* * do{ uuid = (int)(Math.random()*100000); }while(wirelessTxStatusList.containsKey(uuid)); */ for (ServerWirelessTxStatus tx : wirelessTxStatusList.values()) { uuid = Math.max(uuid, tx.uuid); } uuid++; ServerWirelessTxStatus tx; wirelessTxStatusList.put(uuid, tx = new ServerWirelessTxStatus(name, -1, 0, sixNode.coordonate, uuid, this)); sendTx1Syncronise(tx); } break; case serverRxAdd: { int idx = 0; String name = stream.readUTF(); int uuid = 0; /* * do{ uuid = (int)(Math.random()*100000); }while(wirelessTxStatusList.containsKey(uuid)); */ for (ServerWirelessRxStatus rx : wirelessRxStatusList.values()) { uuid = Math.max(uuid, rx.uuid); } uuid++; ServerWirelessRxStatus rx; wirelessRxStatusList.put(uuid, rx = new ServerWirelessRxStatus(name, -1, false, uuid, this)); sendRx1Syncronise(rx); } break; case serverTxConfig: { int uuid = stream.readInt(); String name = stream.readUTF(); int id = stream.readInt(); WirelessTxStatus tx = wirelessTxStatusList.get(uuid); if (tx != null) { tx.setName(name); tx.setId(id); sendTx1Syncronise(tx); } } break; case serverRxConfig: { int uuid = stream.readInt(); String name = stream.readUTF(); int id = stream.readInt(); WirelessRxStatus rx = wirelessRxStatusList.get(uuid); if (rx != null) { rx.setName(name); rx.setId(id); sendRx1Syncronise(rx); } } break; case serverTxDelete: { int uuid = stream.readInt(); ServerWirelessTxStatus tx = wirelessTxStatusList.get(uuid); if (tx != null) { tx.delete(); wirelessTxStatusList.remove(tx.uuid); ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); packet.writeByte(clientTxDelete); packet.writeInt(uuid); // TODO sendPacketToAllClient(bos); } } break; case serverRxDelete: int uuid = stream.readInt(); ServerWirelessRxStatus rx = wirelessRxStatusList.get(uuid); if (rx != null) { rx.delete(); wirelessRxStatusList.remove(uuid); ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); packet.writeByte(clientRxDelete); packet.writeInt(uuid); // TODO sendPacketToAllClient(bos); } break; case serverAllSyncronise: { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream packet = new DataOutputStream(bos); preparePacketForClient(packet); packet.writeByte(clientAllSyncronise); packet.writeInt(wirelessTxStatusList.size()); for (ServerWirelessTxStatus e : wirelessTxStatusList.values()) { e.writeTo(packet); } packet.writeInt(wirelessRxStatusList.size()); for (WirelessRxStatus e : wirelessRxStatusList.values()) { e.writeTo(packet); } sendPacketToClient(bos, player); } break; } } catch (IOException e) { e.printStackTrace(); } } /* * public String getType() { * * return "Probe"; } */ private void setName(String name) { this.name = name; needPublish(); } private void setStation(int port) { removeFromServer(); this.station = port; addToServer(); needPublish(); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setInteger("station", station); nbt.setString("name", name); int idx; nbt.setInteger("txCnt", wirelessTxStatusList.size()); idx = 0; for (ServerWirelessTxStatus tx : wirelessTxStatusList.values()) { tx.writeToNBT(nbt, "tx" + idx); idx++; } nbt.setInteger("rxCnt", wirelessRxStatusList.size()); idx = 0; for (ServerWirelessRxStatus rx : wirelessRxStatusList.values()) { rx.writeToNBT(nbt, "rx" + idx); idx++; } } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); station = nbt.getInteger("station"); name = nbt.getString("name"); int cnt; cnt = nbt.getInteger("txCnt"); for (int idx = 0; idx < cnt; idx++) { ServerWirelessTxStatus tx = new ServerWirelessTxStatus(nbt, "tx" + idx, this); wirelessTxStatusList.put(tx.uuid, tx); } cnt = nbt.getInteger("rxCnt"); for (int idx = 0; idx < cnt; idx++) { ServerWirelessRxStatus rx = new ServerWirelessRxStatus(nbt, "rx" + idx, this); wirelessRxStatusList.put(rx.uuid, rx); } } @Override public boolean hasGui() { return true; } void addToServer() { if (station != -1) { addedOnServer = Eln.modbusServer.add(this); } } void removeFromServer() { if (addedOnServer) Eln.modbusServer.remove(this); addedOnServer = false; } IModbusSlot getModbusSlot(int id) { for (IModbusSlot slot : mapping) { if (id >= slot.getOffset() && id < slot.getOffset() + slot.getSize()) { onActivity(); return slot; } } onError(); return nullSlot; } @Override public boolean getCoil(int id) throws IllegalAddressException { IModbusSlot slot = getModbusSlot(id); id -= slot.getOffset(); return slot.getCoil(id); } @Override public boolean getInput(int id) throws IllegalAddressException { IModbusSlot slot = getModbusSlot(id); id -= slot.getOffset(); return slot.getInput(id); } @Override public short getInputRegister(int id) throws IllegalAddressException { IModbusSlot slot = getModbusSlot(id); id -= slot.getOffset(); return slot.getInputRegister(id); } @Override public int getSlaveId() { return station; } @Override public void setCoil(int id, boolean value) { IModbusSlot slot = getModbusSlot(id); id -= slot.getOffset(); slot.setCoil(id, value); } @Override public void setHoldingRegister(int id, short value) { IModbusSlot slot = getModbusSlot(id); id -= slot.getOffset(); slot.setHoldingRegister(id, value); } }