10 changed files with 261 additions and 171 deletions
After Width: | Height: | Size: 59 KiB |
@ -0,0 +1,206 @@ |
|||||||
|
package de.srsoftware.web4rail.devices; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.TreeMap; |
||||||
|
import java.util.Map.Entry; |
||||||
|
import java.util.concurrent.TimeoutException; |
||||||
|
|
||||||
|
import org.json.JSONObject; |
||||||
|
|
||||||
|
import de.srsoftware.tools.Tag; |
||||||
|
import de.srsoftware.tools.Tools; |
||||||
|
import de.srsoftware.web4rail.BaseClass; |
||||||
|
import de.srsoftware.web4rail.Command; |
||||||
|
import de.srsoftware.web4rail.Command.Reply; |
||||||
|
import de.srsoftware.web4rail.tags.Button; |
||||||
|
import de.srsoftware.web4rail.tags.Fieldset; |
||||||
|
import de.srsoftware.web4rail.tags.Form; |
||||||
|
import de.srsoftware.web4rail.tags.Input; |
||||||
|
import de.srsoftware.web4rail.tags.Radio; |
||||||
|
import de.srsoftware.web4rail.tags.Table; |
||||||
|
import de.srsoftware.web4rail.tags.Window; |
||||||
|
import de.srsoftware.web4rail.Constants; |
||||||
|
import de.srsoftware.web4rail.Protocol; |
||||||
|
|
||||||
|
public class Decoder extends BaseClass implements Constants, Device { |
||||||
|
|
||||||
|
public static final String DECODER = "decoder"; |
||||||
|
public static final String CVS = "cvs"; |
||||||
|
private Integer address = null; |
||||||
|
public TreeMap<Integer,Integer> cvs = new TreeMap<Integer, Integer>(); |
||||||
|
private boolean init = false; |
||||||
|
private Protocol proto = Protocol.DCC128; |
||||||
|
public static final Integer CV_ADDR = 1; |
||||||
|
private static final String ACTION_PROGRAM = "program"; |
||||||
|
private static final String MODE = "mode"; |
||||||
|
private static final String POM = "pom"; |
||||||
|
private static final String TRACK = "track"; |
||||||
|
private static final String VALUE = "val"; |
||||||
|
private static final String CV = "cv"; |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public int address() { |
||||||
|
if (isNull(address)) address = cvs.get(CV_ADDR); |
||||||
|
return address; |
||||||
|
} |
||||||
|
|
||||||
|
public void init() { |
||||||
|
if (init) return; |
||||||
|
String proto = null; |
||||||
|
switch (this.proto) { |
||||||
|
case FLEISCH: |
||||||
|
proto = "F"; break; |
||||||
|
case MOTO: |
||||||
|
proto = "M 2 100 0"; break; // TODO: make configurable
|
||||||
|
case DCC14: |
||||||
|
case DCC27: |
||||||
|
case DCC28: |
||||||
|
case DCC128: |
||||||
|
proto = "N 1 "+this.proto.steps+" 5"; break; // TODO: make configurable
|
||||||
|
case SELECTRIX: |
||||||
|
proto = "S"; break; |
||||||
|
} |
||||||
|
plan.queue(new Command("INIT {} GL "+address()+" "+proto) { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSuccess() { |
||||||
|
super.onSuccess(); |
||||||
|
plan.stream(t("{} initialized.",this)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onFailure(Reply r) { |
||||||
|
super.onFailure(r); |
||||||
|
plan.stream(t("Was not able to initialize {}!",this)); |
||||||
|
} |
||||||
|
}); |
||||||
|
init = true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JSONObject json() { |
||||||
|
JSONObject json = super.json(); |
||||||
|
json.put(CVS, cvs); |
||||||
|
json.put(PROTOCOL, proto); |
||||||
|
return json; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Tag link(String... args) { |
||||||
|
Tools.notImplemented("Decoder.link(…)"); |
||||||
|
return new Tag("span").content("[[Decoder.link() not implemented]]"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Decoder load(JSONObject json) { |
||||||
|
super.load(json); |
||||||
|
if (json.has(PROTOCOL)) proto = Protocol.valueOf(json.getString(PROTOCOL)); |
||||||
|
if (json.has(CVS)) { // Legacy
|
||||||
|
JSONObject jCvs = json.getJSONObject(CVS); |
||||||
|
for (String key : jCvs.keySet()) cvs.put(Integer.parseInt(key),jCvs.getInt(key)); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
private String program(int cv,int val,boolean pom) { |
||||||
|
if (cv != 0) { |
||||||
|
if (val < 0) { |
||||||
|
cvs.remove(cv); |
||||||
|
return null; |
||||||
|
} |
||||||
|
init(); |
||||||
|
Command command = new Command("SET {} SM "+(pom?address():-1)+" CV "+cv+" "+val); |
||||||
|
try { |
||||||
|
Reply reply = plan.queue(command).reply(); |
||||||
|
if (reply.succeeded()) { |
||||||
|
cvs.put(cv, val); |
||||||
|
address = cvs.get(CV_ADDR); // update address field:
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
return reply.message(); |
||||||
|
} catch (TimeoutException e) { |
||||||
|
return t("Timeout while sending programming command!"); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private Fieldset programming() { |
||||||
|
Fieldset fieldset = new Fieldset(t("Programming")).id("props-cv"); |
||||||
|
|
||||||
|
Form form = new Form("cv-form"); |
||||||
|
new Input(REALM,REALM_LOCO).hideIn(form); |
||||||
|
new Input(ID,id()).hideIn(form); |
||||||
|
new Input(ACTION,ACTION_PROGRAM).hideIn(form); |
||||||
|
|
||||||
|
Table table = new Table(); |
||||||
|
table.addHead(t("setting"),t("CV"),t("value"),t("actions")); |
||||||
|
for (int cv=1; cv<19; cv++) { |
||||||
|
Object val = cvs.get(cv); |
||||||
|
if (isNull(val)) { |
||||||
|
if (Set.of(7, 8, 10, 11, 12, 13, 14, 15, 16).contains(cv)) continue; |
||||||
|
val = t("no value"); |
||||||
|
} |
||||||
|
table.addRow(setting(cv),cv,val,new Button(t("edit"), "copyCv(this);")); |
||||||
|
} |
||||||
|
for (Entry<Integer, Integer> entry : cvs.entrySet()){ |
||||||
|
int cv = entry.getKey(); |
||||||
|
if (cv<10) continue; |
||||||
|
int val = entry.getValue(); |
||||||
|
table.addRow(setting(cv),cv,val,new Button(t("edit"), "copyCv(this);")); |
||||||
|
} |
||||||
|
Tag mode = new Tag("div"); |
||||||
|
new Radio(MODE, POM, t("program on main"), true).addTo(mode); |
||||||
|
new Radio(MODE, TRACK, t("prgramming track"), false).addTo(mode); |
||||||
|
table.addRow(mode,new Input(CV,0).numeric(),new Input(VALUE,0).numeric(),new Button(t("Apply"),form)); |
||||||
|
return table.addTo(form).addTo(fieldset); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm, String... errorMessages) { |
||||||
|
Tag div = new Tag("div"); |
||||||
|
for (Protocol proto : Protocol.values()) { |
||||||
|
new Radio(PROTOCOL, proto.toString(), t(proto.toString()), proto == this.proto).addTo(div); |
||||||
|
} |
||||||
|
formInputs.add(t("Protocol"),div); |
||||||
|
formInputs.add(t("Address"),new Input(ADDRESS, address).numeric()); |
||||||
|
postForm.add(programming()); |
||||||
|
return super.properties(preForm, formInputs, postForm, errorMessages); |
||||||
|
} |
||||||
|
|
||||||
|
public Protocol protocol() { |
||||||
|
return proto; |
||||||
|
} |
||||||
|
|
||||||
|
public void setProtocol(Protocol proto) { |
||||||
|
this.proto = proto; |
||||||
|
} |
||||||
|
|
||||||
|
private Object setting(int cv) { |
||||||
|
switch (cv) { |
||||||
|
case 1: |
||||||
|
return t("Address"); |
||||||
|
case 2: |
||||||
|
return t("minimum starting voltage v<sub>min</sub>"); |
||||||
|
case 3: |
||||||
|
return t("starting delay"); |
||||||
|
case 4: |
||||||
|
return t("braking delay"); |
||||||
|
case 5: |
||||||
|
return t("maximum speed v<sub>max</sub>"); |
||||||
|
case 6: |
||||||
|
return t("mid speed v<sub>mid</sub>"); |
||||||
|
case 9: |
||||||
|
return t("PWM rate"); |
||||||
|
case 17: |
||||||
|
case 18: |
||||||
|
return t("extended address"); |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue