Last modified by sndueste on 2024/03/13 14:48

From version 3.1
edited by sendels
on 2019/08/07 08:40
Change comment: added attachments and links
To version 11.1
edited by sndueste
on 2021/10/14 10:19
Change comment: There is no comment for this version

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.sendels
1 +XWiki.sndueste
Tags
... ... @@ -1,0 +1,1 @@
1 +how-to|favourite
Content
... ... @@ -1,20 +1,8 @@
1 -==
2 -(% class="twikiTocTitle" %)Contents(%%) ==
1 +(% class="twikiTocTitle" %)Content
3 3  
4 -* [[Introduction>>doc:||anchor="Introduction"]]
5 -* [[Train ID reading with local ID reader (Advanced ID Server) recommended>>doc:||anchor="Train ID reading with local ID reader (Advanced ID Server) recommended"]]
6 -** [[What does Advanced ID Server do?>>doc:||anchor="What does Advanced ID Server do?"]]
7 -** [[Addresses>>doc:||anchor="Addresses"]]
8 -** [[Resources>>doc:||anchor="Resources"]]:
9 -* [[Direct reading of Train ID>>doc:||anchor="Direct reading of Train ID"]]
10 -* [[Train ID sender program (TIDS) obsolete>>doc:||anchor="Train ID sender program (TIDS) obsolete"]]
11 -* [[Train ID Yelling server (TIDY)>>doc:||anchor="Train ID Yelling server (TIDY)"]]
12 -** [[Known Issues>>doc:||anchor="Known Issues"]]
13 -* [[Short presentation by Fini>>doc:||anchor="Short presentation by Fini"]]
14 14  
15 -\\
16 16  
17 -\\
5 +{{toc/}}
18 18  
19 19  == Introduction ==
20 20  
... ... @@ -26,7 +26,7 @@
26 26  
27 27  Each //pulse train// is identified by an **//Train ID//** (synonyms: **//bunch ID, timestamp//**).
28 28  
29 -Recording this Train ID on the user side allows the correlation of data acquired by the user with all the data saved at FLASH in the DOOCS system, especially with the photon intensity data measured by the [[GMD>>doc:FLASHUSER.Gas Monitor Detector]] system.
17 +Recording this Train ID on the user side allows the correlation of data acquired by the user with all the data saved at FLASH in the DOOCS system, especially with the photon intensity data measured by the GMD system.
30 30  
31 31  Within DOOCS the Train ID is a 32-bit number. For the users it is transmitted via a socket connection over ethernet - TCP socket. The ID is set 20 ms before the train starts and stays 80 ms after the train. To read the Train ID by the user there are 2 options provided by FLASH:
32 32  
... ... @@ -33,7 +33,9 @@
33 33  * using a provided program (AdvancedIDServer.exe) running on the user's machine, that synchronizes with the Train ID sender and uses the local clock of the user computer to lower the jitter in reading the ID significantly. The user program connects then locally to the AdvancedIDServer program to get the ID ...
34 34  * direct reading of the ID via TCP socket
35 35  
36 -[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/aids_principle.png~|~|alt="aids_principle.png" width="440" height="289"~]~]>>attach:aids_principle.png]]
24 +[[image:attach:aids_principle.png||height="400"]]
25 +
26 +
37 37  Basic pinciple of Train ID distribution at Flash1 with TIDS and AIDS
38 38  
39 39  See also this [[sketch>>attach:timing.png]] of the sequence with miliseconds attached to it, to see when the ID updates relative to the beam.
... ... @@ -40,17 +40,17 @@
40 40  
41 41  Note: If the central Train ID server crashes it will not resume the ID numbers where it was. In most times it will restart with ID 0, sometimes it is set to some high number by hand. For this reason you will see Train IDs with some high bit not as often as expected.
42 42  
43 -\\
33 +[[Contents>>doc:||anchor="Contents"]]
44 44  
45 45  == Train ID reading with local ID reader (Advanced ID Server) //recommended// ==
46 46  
47 47  === What does //Advanced ID Server// do? ===
48 48  
49 -It connects to the TCP based TIDY or TIDS server and continuously gets the Ethernet packets with the IDs. These packets are time stamped with microsecond resolution and stored. This runs all the time. Because we have a lot of data we can correlate the local time on that machine (that generated the local time stamps) and the IDs. If the Ethernet connection lags sometimes, chokes, hick ups and messes around with our packets, even drops some... Who cares. By closely monitoring all data we can define a function to calculate the Train ID from the local time on that machine.
39 +It connects to the TCP based TIDS server and continuously gets the Ethernet packets with the IDs. These packets are time stamped with microsecond resolution and stored. This runs all the time. Because we have a lot of data we can correlate the local time on that machine (that generated the local time stamps) and the IDs. If the Ethernet connection lags sometimes, chokes, hick ups and messes around with our packets, even drops some... Who cares. By closely monitoring all data we can define a function to calculate the Train ID from the local time on that machine.
50 50  
51 -[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/AIDS_running.png~|~|alt="Advanced ID Server running"~]~]>>attach:AIDS_running.png]]
41 +[[image:attach:AIDS_running.png||height="189"]]
52 52  
53 -* Short presentation by Fini
43 +\\
54 54  
55 55  Here it is running on Windows, but of course you can also use it on your Linux machine (build it from the source).
56 56  
... ... @@ -107,6 +107,8 @@
107 107  * [[attach:AdvancedIDServer-inline.vi]]: Example how to use the Advanced ID Server with Labview (LV11)
108 108  * [[AdvancedIDServer on github~[~[image:url:http://hasfweb.desy.de/pub/TWiki/TWikiDocGraphics/external-link.gif~|~|width="13" height="12"~]~]>>url:https://github.com/Finii/AdvancedIDServer||shape="rect"]]
109 109  
100 +[[Contents>>doc:||anchor="Contents"]]
101 +
110 110  == Direct reading of Train ID ==
111 111  
112 112  Receiving the Train ID via ethernet is rather simple. Just open a TCP socket to the one of the servers and read from it.
... ... @@ -116,7 +116,6 @@
116 116  
117 117  * [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]:58050 (TIDY (//for Flash1//))
118 118  * [[flash2cpuxgmd2.desy.de>>url:http://flash2cpuxgmd2.desy.de||shape="rect"]]:58050 (TIDY (//for Flash2//))
119 -* [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]]:58050 (TIDS) (obsolete)
120 120  
121 121  Please see also the sample code for [[C>>attach:bunch-id_readout.c]] and [[LabView 14>>attach:bunch-id_readout.vi]]. Example how to embed the ethernet Train ID code into your Labview project (LV 8.6): [[attach:BunchID-inline.vi]]. We have also [[C++ code>>attach:event-reader.hh]] which can be used to be integrate into existing projects.
122 122  
... ... @@ -147,22 +147,8 @@
147 147  
148 148  The time and date have leading zeros as necessary to ensure a constant field width. The ID number is not zero padded and thus has a varying field width.
149 149  
150 -\\
141 +[[Contents>>doc:||anchor="Contents"]]
151 151  
152 -== Train ID sender program (TIDS) //obsolete// ==
153 -
154 -The sender program is currently running on [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]]. It can be restarted if there are problems (Event_ID_Server). It can be changed to continuously delivers Train IDs (uncheck "fast shutter eventIDs") or deliver IDs only if the fast shutter is open at this moment (check "fast shutter eventIDs" as in the example below).
155 -
156 -Address:
157 -
158 -* [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]:58050
159 -
160 -Do not enable "fast shutter eventIDs" if you want to use the Advanced ID Server.
161 -
162 -[[~[~[image:url:http://hasfweb.desy.de/pub/Setup/TrainID/Clipboard02.png~|~|alt="Clipboard02.png" width="470" height="420"~]~]>>attach:Clipboard02.png]]
163 -
164 -The TIDY: known issues also apply here.
165 -
166 166  \\
167 167  
168 168  == Train ID Yelling server (TIDY) ==
... ... @@ -195,7 +195,7 @@
195 195  * 20.9.18: The .exe always try [[hasfhvctrl.desy.de>>url:http://hasfhvctrl.desy.de||shape="rect"]] first. So start with additional parameter via the commandline.
196 196  [[attach:AdvancedIDServer.exe]] [[hasfcpuexp2.desy.de>>url:http://hasfcpuexp2.desy.de||shape="rect"]]
197 197  
198 -\\
175 +[[Contents>>doc:||anchor="Contents"]]
199 199  
200 200  == Short presentation by Fini ==
201 201  
AIDS_running.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +5.4 KB
Content
AdvancedIDServer-inline.vi
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +16.2 KB
Content
AdvancedIDServer.exe
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +129.9 KB
Content
BunchID-inline.vi
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +32.1 KB
Content
Clipboard02.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +103.0 KB
Content
aids_principle.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +40.5 KB
Content
bunch-id_readout.c
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +5.3 KB
Content
... ... @@ -1,0 +1,226 @@
1 +/*
2 + * Copyright 2014, DESY
3 + *
4 + * This program is free software; you can redistribute it and/or modify it
5 + * under the terms of the GNU General Public License as published by the
6 + * Free Software Foundation; either version 2 of the License, or (at your
7 + * option) any later version.
8 + */
9 +
10 +#ifdef WIN32
11 +# ifdef _MSC_VER
12 +# undef UNICODE
13 +# define _CRT_SECURE_NO_WARNINGS
14 +# define snprintf _snprintf_s
15 +# pragma comment(lib, "ws2_32.lib")
16 +# endif
17 +# include <winsock2.h>
18 +# include <ws2tcpip.h>
19 +# include <stdio.h>
20 +# include <stdlib.h>
21 +# include <string.h>
22 +# include <errno.h>
23 +#else
24 +# include <errno.h>
25 +# include <stdio.h>
26 +# include <stdlib.h>
27 +# include <string.h>
28 +# include <unistd.h>
29 +# include <sys/types.h>
30 +# include <sys/socket.h>
31 +# include <netinet/in.h>
32 +# include <netdb.h>
33 +#endif
34 +
35 +/* SO_REUSEPORT is not supported by older systems
36 + *
37 + * see http://stackoverflow.com/questions/3261965/so-reuseport-on-linux
38 + * > On Linux, SO_REUSEADDR provide most of what SO_REUSEPORT
39 + * > provides on BSD. */
40 +#ifndef SO_REUSEPORT
41 +#define SO_REUSEPORT SO_REUSEADDR
42 +#endif
43 +
44 +#ifndef ARRAY_SIZE
45 +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
46 +#endif
47 +
48 +#define MAX_HOSTNAME_LEN 128
49 +#define MAX_SERVICE_LEN 32
50 +
51 +#define DEFAULT_HOSTNAME "hasfhvctrl"
52 +#define DEFAULT_SERVICE "58050"
53 +
54 +static int parse_and_print(const char *str)
55 +{
56 + int hour = 0, minute = 0, second = 0, msecond = 0;
57 + int year = 0, month = 0, day = 0;
58 + int eventid = 0;
59 + int ret;
60 +
61 + ret = sscanf(str, "%2d%2d%2d %2d%2d%2d.%3d %x\n",
62 + &year, &month, &day, &hour, &minute, &second, &msecond,
63 + &eventid);
64 + if (ret != 8) {
65 + fprintf(stderr, "Parsing [%s] failed\n", str);
66 + return -EINVAL;
67 + }
68 +
69 + printf("%02d%02d%02d %02d%02d%02d.%03d %X\n",
70 + year, month, day, hour, minute, second, msecond,
71 + eventid);
72 + return 0;
73 +}
74 +
75 +/*
76 + * This sample shows the basic steps needed to receive the Event-ID.
77 + *
78 + * 0) Do some commanline parsing
79 + * 1) Open a socket to the server providing the data
80 + * a) Resolve the hostname
81 + * b) Create the socket
82 + * c) Bind to specific local port (optional)
83 + * d) Connect to the remote machine
84 + * 2) Wait for data
85 + * 3) Read the data and parse it
86 + * 4) Do something with it (print them)
87 + * 5) Back to step 2
88 + *
89 + * To build it under linux type:
90 + * gcc -o bunchid bunch-id_readout.c
91 + */
92 +int main(int argc, char *argv[])
93 +{
94 +#ifdef WIN32
95 + WSADATA wsaData;
96 +#endif
97 + char hostname[MAX_HOSTNAME_LEN];
98 + char service[MAX_SERVICE_LEN];
99 + struct addrinfo *ai = NULL;
100 + struct sockaddr_in local;
101 + struct addrinfo hints;
102 + struct timeval to;
103 + char buffer[128];
104 + fd_set fdset;
105 + int opt = 1;
106 + int sockfd;
107 + int ret;
108 + int i;
109 +
110 + /* check for user input */
111 + switch (argc) {
112 + case 1:
113 + /* no arguments given */
114 + strcpy(hostname, DEFAULT_HOSTNAME);
115 + strcpy(service, DEFAULT_SERVICE);
116 + break;
117 + case 2:
118 + snprintf(hostname, ARRAY_SIZE(hostname), "%s", argv[1]);
119 + strcpy(service, DEFAULT_SERVICE);
120 + break;
121 + case 3:
122 + snprintf(hostname, ARRAY_SIZE(hostname), "%s", argv[1]);
123 + snprintf(service, ARRAY_SIZE(service), "%s", argv[2]);
124 + break;
125 + default:
126 + printf("usage: %s [hostname] [port]\n", argv[0]);
127 + return 1;
128 + }
129 +
130 +#ifdef WIN32
131 + memset(&wsaData, 0, sizeof(wsaData));
132 + ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
133 + if (ret != 0) {
134 + printf("Init winsock failed\r\n");
135 + return 1;
136 + }
137 +#endif
138 +
139 + printf("Connecting to %s:%s...\n", hostname, service);
140 +
141 + /* prepare variables */
142 + memset(buffer, 0, ARRAY_SIZE(buffer));
143 + memset(&hints, 0, sizeof(hints));
144 + hints.ai_family = AF_INET;
145 + hints.ai_socktype = SOCK_STREAM;
146 +
147 + /* resolve hostname */
148 + ret = getaddrinfo(hostname, service, &hints, &ai);
149 + if (ret < 0) {
150 + fprintf(stderr, "Unable to resolve: %s: %s\n",
151 + hostname, gai_strerror(-ret));
152 + return -ENOENT;
153 + }
154 + /* open tcp socket */
155 + sockfd = socket(AF_INET, SOCK_STREAM, 0);
156 + if (sockfd < 0) {
157 + fprintf(stderr, "socket failed: %s\n",
158 + strerror(errno));
159 + goto cleanup;
160 + }
161 +
162 + /* allow port reuse (optional, linux only) */
163 + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt));
164 + if (ret < 0)
165 + fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
166 +
167 + /* bind to specific local port (optional) */
168 + memset(&local, 0, sizeof(local));
169 + local.sin_family = AF_INET;
170 + local.sin_addr.s_addr = INADDR_ANY;
171 + local.sin_port = htons(atoi(DEFAULT_SERVICE));
172 +
173 + ret = bind(sockfd, (const struct sockaddr *)&local, sizeof(local));
174 + if (ret < 0) {
175 + fprintf(stderr, "bind to port " DEFAULT_SERVICE
176 + " failed: %s\n", strerror(errno));
177 + goto cleanup;
178 + }
179 +
180 + /* connect to remote machine */
181 + ret = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
182 + if (ret < 0) {
183 + fprintf(stderr, "connect to %s:%s failed: %s\n",
184 + hostname, service, strerror(errno));
185 + goto cleanup;
186 + }
187 +
188 + FD_ZERO(&fdset);
189 +
190 + /* enter receive loop */
191 + printf("YYMMDD HHMMSS.mmm BUNCHID\n");
192 + for (i = 0; i < 3; i++) {
193 + /* reset timeout, see select recommendations */
194 + to.tv_sec = 10;
195 + to.tv_usec = 0;
196 + FD_SET(sockfd, &fdset);
197 + /* wait for data */
198 + ret = select(sockfd+1, &fdset, NULL, NULL, &to);
199 + if (ret < 0) {
200 + fprintf(stderr, "select failed with: %d -> %d -> %s\n",
201 + ret, errno, strerror(errno));
202 + break;
203 + }
204 + /* read bunch-id */
205 + ret = recv(sockfd, buffer, ARRAY_SIZE(buffer), 0/*flags*/);
206 + if (ret < 0) {
207 + fprintf(stderr, "receive from %s:%s failed: %s\n",
208 + hostname, service, strerror(errno));
209 + goto cleanup;
210 + }
211 + /* print bunch-id */
212 + parse_and_print(buffer);
213 + }
214 +
215 +cleanup:
216 + freeaddrinfo(ai);
217 + if (sockfd)
218 +#ifdef WIN32
219 + closesocket(sockfd);
220 + WSACleanup();
221 +#else
222 + close(sockfd);
223 +#endif
224 + return 0;
225 +}
226 +
bunch-id_readout.vi
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +7.3 KB
Content
event-reader.hh
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +3.7 KB
Content
... ... @@ -1,0 +1,165 @@
1 +/*
2 + * Copyright 2015-2016, DESY
3 + *
4 + * This program is free software; you can redistribute it and/or modify it
5 + * under the terms of the GNU General Public License as published by the
6 + * Free Software Foundation; either version 2 of the License, or (at your
7 + * option) any later version.
8 + *
9 + * NOTE:
10 + * Under windows a recent PSDK is required. Feb 2003 is last known to
11 + * work with WinXP and VC6.
12 + */
13 +
14 +#ifdef WIN32
15 +# include <winsock2.h> // struct timeval
16 +#else
17 +# include <stdint.h>
18 +#endif
19 +
20 +#include <time.h>
21 +#include <string>
22 +
23 +#pragma once
24 +
25 +/**
26 + * This interface can be used to pass messages from the event reader
27 + * to the embedding application.
28 + */
29 +struct ILogger {
30 +
31 + /** message severity */
32 + enum Level {
33 + LEVEL_ERROR,
34 + LEVEL_WARNING,
35 + LEVEL_INFO,
36 + LEVEL_DEBUG
37 + };
38 +
39 + virtual ~ILogger() {}
40 +
41 + /**
42 + * Writes a message from the EventReader.
43 + *
44 + * @param lvl[in] The severity of the message
45 + * @param msg[in] The message to print
46 + */
47 + virtual void log(enum Level in, const char *msg) = 0;
48 +};
49 +
50 +#if defined(WIN32) && (_MSC_VER < 1300)
51 +typedef signed __int64 int64_t;
52 +typedef unsigned __int64 uint64_t;
53 +#endif
54 +
55 +/**
56 + * This collects all event data
57 + */
58 +struct EventInfo {
59 + /** The event id */
60 + uint64_t id;
61 + /** When did the event appear */
62 + struct timeval time;
63 +
64 + /** Create a blank info object */
65 + EventInfo() : id(-1) { }
66 +};
67 +
68 +/**
69 + * This is the interface definition for event listeners.
70 + *
71 + * Implement this interface to register at the event-source
72 + * and become notified.
73 + */
74 +struct IEventIDListener
75 +{
76 + virtual ~IEventIDListener() {}
77 + /**
78 + * Called when-ever a new event-id is available.
79 + *
80 + * @param event[in] The new event-info
81 + */
82 + virtual void updateEventInfo(const struct EventInfo &) = 0;
83 + /**
84 + * Called if we have lost the connection and the will be no more
85 + * event notifications.
86 + *
87 + * @param err[in] The error code leading to the problem
88 + */
89 + virtual void connectionLost(int) { /* dummy */ }
90 +};
91 +
92 +/**
93 + * This class wraps the required code to receive event notifications.
94 + *
95 + * It is implemented as singleton, so it is easy to handle within existing
96 + * code bases. Please note that the notification is not async, so if your
97 + * listener is blocking or delaying the call you will run into trouble.
98 + *
99 + * Usage:
100 + *
101 + * Implement you own IEventIDListener
102 + * Register your listener on the reader
103 + * Connect the reader to the source
104 + *
105 + * Now you will receive updated event information
106 + */
107 +class EventReader
108 +{
109 + EventReader() {}
110 + /* Do not allow to create a copy of the instance */
111 + EventReader(const EventReader&) { }
112 + EventReader& operator=(const EventReader&) { return *this; }
113 +
114 +public:
115 + ~EventReader() {}
116 + /**
117 + * Returns the only allowed instance.
118 + */
119 + static EventReader* getInstance();
120 +
121 + /**
122 + * (Un/)Register listeners from the event reader.
123 + *
124 + * @param listener[in] The listener to (un-)register.
125 + *
126 + * @see #enableNotification
127 + */
128 + void registerListener(IEventIDListener *);
129 + void unregisterListener(IEventIDListener *);
130 + /**
131 + * (Re)connect to the event source
132 + *
133 + * @param host[in] The host to connect to.
134 + * @param port[in] The server to use.
135 + *
136 + * @return 0 on success, otherwise negative error code.
137 + *
138 + * @see #enableNotification
139 + */
140 + int connect(const std::string &, unsigned);
141 +
142 + /**
143 + * Enable or disable the notification
144 + */
145 + void enableNotification(bool enable = true);
146 + bool notificationEnabled() const;
147 +
148 + /**
149 + * Requests the latest available info set. This provides
150 + * the same information as the callback, but on request.
151 + * The notification can be set to off.
152 + *
153 + * @param event[out] The info to fill.
154 + */
155 + void getRecent(struct EventInfo &event);
156 +
157 + /**
158 + * Assigns the logger to be used to write messages. If NULL is
159 + * passed, the default logger is used again.
160 + *
161 + * @param logger[in] The new logger to use
162 + */
163 + void setLogger(struct ILogger *logger);
164 +};
165 +
eventid.pdf
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +1.4 MB
Content
timing.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.XWikiGuest
Size
... ... @@ -1,0 +1,1 @@
1 +211.5 KB
Content