1 module finedge.ext.connectors;
2 
3 import haystack.tag;
4 import haystack.filter;
5 import std.typecons;
6 import std.conv;
7 import std.array;
8 import std.range;
9 import core.time;
10 
11 export:
12 shared interface ConnContext
13 {
14 	@property shared(IIntegratedConnectorImpl) conn();
15 	@property immutable(Dict) record();
16 	@property immutable(TuningPolicy) tuningPolicy();
17 	//@property shared(TagDatabase) db();
18 	void * callSharedMethod(string extName, string methodName, shared(void*)[] args...);
19 }
20 
21 shared interface ExtensionLibrary
22 {
23 	void * callFunction(string name, shared(void*)[] args...);
24 }
25 
26 immutable struct TuningPolicy
27 {
28 	Dict record;
29 	string name					= "default";
30 	Duration pollInterval		= dur!("seconds")(1);
31 	Duration staleExpiration	= dur!("minutes")(5);
32 	Duration maxWriteInterval;
33 	Duration minWriteInterval;
34 
35 	private this(immutable(Dict) record)
36 	{
37 		this.record	= record;
38 		this.name	= record.get!Str("name").val;
39 
40 		if (record.has("pollTime"))
41 			this.pollInterval		= dur!("seconds")(cast (long) record.get!Num("pollTime").val);
42 
43 		if (record.has("staleTime"))
44 			this.staleExpiration	= dur!("seconds")(cast (long) record.get!Num("staleTime").val);
45 
46 		if (record.has("maxWriteTime"))
47 			this.maxWriteInterval	= dur!("seconds")(cast (long) record.get!Num("maxWriteTime").val);
48 
49 		if (record.has("minWriteTime"))
50 			this.minWriteInterval	= dur!("seconds")(cast (long) record.get!Num("minWriteTime").val);
51 	}
52 
53 	@property bool hasMinWrite()
54 	{
55 		return (this.minWriteInterval != Duration.init);
56 	}
57 	
58 	@property bool hasMaxWrite()
59 	{
60 		return (this.maxWriteInterval != Duration.init);
61 	}
62 
63 	@property immutable(Ref) id()
64 	{
65 		if (this.record == Dict.init)
66 			return Ref.init;
67 
68 		return this.record.id;
69 	}
70 	
71 	static TuningPolicy fromRec(immutable(Dict) record)
72 	{
73 		return TuningPolicy(record);
74 	}
75 }
76 
77 
78 shared abstract class ExtensionConnector
79 {
80 	protected shared(ConnContext) context;
81 
82 	void setContext(shared(ConnContext) context)
83 	{
84 		this.context	= context;
85 	}
86 
87 	abstract immutable(Dict) onOpen();
88 	abstract void onClose();
89 	abstract void onPoll();
90 	abstract void onWrite(shared(ConnPoint) point, Tag value, int level, string who);
91 	abstract immutable(Grid) onLearn(Tag token = Na());
92 	abstract void onPointChange(shared(ConnPoint) point, immutable(Dict) changes);
93 	abstract void onWatch(shared(ConnPoint)[] points);
94 	abstract void onUnwatch(shared(ConnPoint)[] points);
95 	abstract void onHouseKeeping();
96 	abstract void onShutdown();
97 
98 
99 	final void open()
100 	{
101 		this.context.conn.send(ConnMsg.make("open"));
102 	}
103 	
104 	final void openPin(string name)
105 	{
106 		this.context.conn.send(ConnMsg.make("open", Str(name).tag));
107 	}
108 
109 	final void close()
110 	{
111 		this.context.conn.send(ConnMsg.make("close"));
112 	}
113 
114 	final void closePin(string name)
115 	{
116 		this.context.conn.send(ConnMsg.make("close", Str(name).tag));
117 	}
118 }
119 
120 shared abstract class NativeEdgeExtension : EdgeExtensionImpl
121 {
122 	// TODO: Make DB query and commit aliases. So that the extension can manipulate the db
123 }
124 
125 shared interface EdgeExtensionImpl
126 {
127 	void onStart();
128 	void onStop();
129 	void onEnable();
130 	void onDisable();
131 	void onUnload();
132 	void onChange(immutable(Dict) changes);
133 	immutable(Grid) onDiscover(Tag params = Tag.init);
134 }
135 
136 shared interface IIntegratedConnectorImpl
137 {
138 	@property immutable(Dict) record();
139 	@property immutable(TuningPolicy) tuningPolicy();
140 	@property shared(ConnPoint)[] watchedPoints();
141 	@property shared(ConnPoint[Ref]) pointTable();
142 	@property bool isOpen();
143 	void send(immutable(ConnMsg) message);
144 	
145 }
146 
147 shared interface ConnPoint
148 {
149 	enum Status {unknown, ok, overridden, stale, fault, down}
150 
151 	@property Ref id();
152 	@property Status currentStatus();
153 	@property Status writeStatus();
154 	@property Tag currentValue();
155 	@property int currentPriority();
156 	@property Tag[] priorityArray();
157 	@property MonoTime lastReadTime();
158 	@property MonoTime lastWriteTime();
159 	@property shared(Dict) rec();
160 	void refreshRecord();
161 
162 	void updateWriteError(Error error);
163 	void updateReadError(Error error);
164 	void updateWriteOk(immutable(Tag) value, int priority);
165 	void updateReadOk(immutable(Tag) value, int priority);
166 }
167 
168 immutable class ConnMsg
169 {
170 	string name;
171 	Tag[] data;
172 
173 	this(string name)
174 	{
175 		this.name	= name;
176 		this.data	= null;
177 	}
178 
179 	this(string name, immutable(Tag)[] data)
180 	{
181 		this.name	= name;
182 		this.data	= data;
183 	}
184 
185 	bool hasData()
186 	{
187 		return (this.data !is null);
188 	}
189 
190 	public static immutable(ConnMsg) make(string name)
191 	{
192 		return new immutable ConnMsg(name);
193 	}
194 
195 
196 	public static immutable(ConnMsg) make(string name, immutable(Tag)[] data)
197 	{
198 		return new immutable ConnMsg(name, data);
199 	}
200 
201 	public static immutable(ConnMsg) make(string name, immutable(Tag) data)
202 	{
203 		return new immutable ConnMsg(name, [data]);
204 	}
205 }