├── LICENSE
├── calvec
├── mgraph
├── mkgraph
├── monit
├── monit2
├── noisemon
├── dayboxer
├── nmonit
├── noisegraph
├── noisemon.grc
└── readme.md
├── parselog
├── readme.md
├── specmon-v1.md
├── specmon.grc
├── specmon2.grc
├── specmon2_gui.grc
├── specmon2_replay.grc
├── specmon_cli.grc
├── specreceive.grc
├── testspec
└── weekgraph
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/calvec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | #
3 | # Description: Calculate a calibration-vector for specmon2
4 | #
5 | # Author: Bart Somers PE1RIK
6 | #
7 |
8 | import argparse
9 | import array #used for fromfile
10 | import numpy as np
11 |
12 | parser = argparse.ArgumentParser()
13 | parser.add_argument('-i', '--infile', type=str, help='Filename with vectors', required=False)
14 | parser.add_argument('-o', '--outfile', type=str, help='Filename where to put output', required=True)
15 | parser.add_argument('-c', '--constant', type=float, help='Constant to use for calculation', required=True)
16 | parser.add_argument('-l', '--length', type=int, help='Vector-length to parse', required=True)
17 | args = parser.parse_args()
18 |
19 | constant_array = [args.constant] * args.length
20 | readlist = array.array('f')
21 |
22 | # Name: DerdeMethode
23 | # Desc: Create a calibration-vector, based on the inputvector
24 | # Input: readlist, outputfile, contstant
25 | # Output: Calibration vector in outputfile
26 | # Return: -
27 | def DerdeMethode(readlist,outputfile, constant):
28 | testout = array.array('f')
29 | for i in range(len(readlist)):
30 | res = constant - readlist[i]
31 | testout.append(float(res))
32 |
33 | #print (testout)
34 | fout = open(outputfile,'wb')
35 | testout.tofile(fout)
36 | fout.close()
37 |
38 | if args.infile:
39 | # Input file is defined. Create a calibration outputfile
40 |
41 | f=open(args.infile,"rb")
42 |
43 | # Skip first few lines
44 | for i in range(20):
45 | readlist.fromfile(f, args.length)
46 | del readlist[:]
47 |
48 | ## Now read the vector to use
49 | #readlist.fromfile(f, args.length)
50 | #f.close()
51 |
52 | # 210927 Test for more vectors
53 | # Base is 5 vectors per second.
54 | # 20 vectors = 4 seconds
55 | # 300 vectors = 1 minute
56 | vecavg = 20
57 | e = np.zeros(args.length)
58 | for i in range(vecavg):
59 | readlist.fromfile(f, args.length)
60 | #print ("len readlist: ", len(readlist), " len e: ", len(e))
61 | e = np.add(e,readlist)
62 | # Now clear the list from file.
63 | del readlist[:]
64 |
65 | # Divide by number of vectors
66 | readlist = np.divide(e,vecavg)
67 | f.close()
68 |
69 | # Write the vector to file
70 | DerdeMethode(readlist, args.outfile, args.constant)
71 | else:
72 | # Inputfile is not defined. Create a vector with only the constant value
73 | constant_array = array.array('f', [args.constant] * args.length)
74 | fout = open(args.outfile,'wb')
75 | constant_array.tofile(fout)
76 | fout.close()
77 |
78 | exit(0)
79 |
80 |
--------------------------------------------------------------------------------
/mgraph:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description: Wrapper to create daily graphs from parsed logfile
4 | #
5 | # Author: Bart Somers PE1RIK
6 | #
7 |
8 | # Select the gnuplot-pallet to use. Suggestion: bentcoolwarm.pal
9 | PALLET=/mnt/space/bart/Download/gnuplot-palettes/bentcoolwarm.pal
10 |
11 | if [ ! -f ${PALLET} ];
12 | then
13 | echo "GNUPLOT Pallet ${PALLET} not found"
14 | exit 1
15 | fi
16 |
17 | if [ -z $1 ];
18 | then
19 | echo "Usage: $0 "
20 | exit 1
21 | else
22 |
23 | OUTFILE=${1}
24 | fi
25 |
26 | #OUTFILE=${OUTFILE}-test
27 |
28 | gnuplot <<- EOF
29 | set terminal png size 1280,768
30 | set output '${OUTFILE}-month-percent.png'
31 | #set xrange [0:23]
32 | set xlabel "Day"
33 | set ylabel "Hour"
34 | set yrange [0:23]
35 | set cblabel "Percentage of usage"
36 | unset key
37 | load '${PALLET}'
38 | plot "${OUTFILE}" using 12:2:6 with image pixels
39 |
40 |
41 | set terminal png size 1280,768
42 | set output '${OUTFILE}-month-opening.png'
43 | #set xrange [0:23]
44 | set xlabel "Day"
45 | set ylabel "Hour"
46 | set yrange [0:23]
47 | set cblabel "Number of openings"
48 | unset key
49 | load '${PALLET}'
50 | plot "${OUTFILE}" using 12:2:10 with image pixels
51 |
52 |
53 | set terminal png size 1280,768
54 | set output '${OUTFILE}-month-avgopen.png'
55 | #set xrange [0:23]
56 | set xlabel "Day"
57 | set ylabel "Hour"
58 | set yrange [0:23]
59 | set cblabel "Avg open time (s)"
60 | unset key
61 | load '${PALLET}'
62 | plot "${OUTFILE}" using 12:2:14 with image pixels
63 |
64 |
65 | set terminal png size 1280,768
66 | set output '${OUTFILE}-month-maxopen.png'
67 | #set xrange [0:23]
68 | set xlabel "Day"
69 | set ylabel "Hour"
70 | set yrange [0:23]
71 | set cblabel "Max open value"
72 | unset key
73 | load '${PALLET}'
74 | plot "${OUTFILE}" using 12:2:16 with image pixels
75 |
76 | EOF
77 |
--------------------------------------------------------------------------------
/mkgraph:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description: Wrapper to create daily graphs from parsed logfile
4 | #
5 | # Author: Bart Somers PE1RIK
6 | #
7 |
8 | if [ -z $1 ];
9 | then
10 | echo "Usage: $0 "
11 | exit 1
12 | else
13 |
14 | BESTAND=${1}
15 | fi
16 |
17 | #OUTBESTAND=${BESTAND}-test
18 | OUTBESTAND=${BESTAND}
19 |
20 | gnuplot <<- EOF
21 | set terminal pngcairo size 1024,768
22 | set output '${OUTBESTAND}-percent.png'
23 | set style fill solid 0.5
24 | set style data histograms
25 | set yrange [0:100]
26 | set xrange [0:24]
27 | set xlabel "Hours"
28 | set ylabel "Percent"
29 | plot "${BESTAND}" using 6 linecolor rgb '#0072bd'
30 | #plot "$BESTAND" using 2:6 linecolor rgb '#0072bd'
31 |
32 | set output '${OUTBESTAND}-opening.png'
33 | set style fill solid 0.5
34 | set style data histograms
35 | unset yrange
36 | set xrange [0:24]
37 | set xlabel "Hours"
38 | set ylabel "Number of openings"
39 | plot "${BESTAND}" using 10 linecolor rgb '#4dbeee'
40 |
41 | set output '${OUTBESTAND}-avgopen.png'
42 | set style fill solid 0.5
43 | set style data histograms
44 | unset yrange
45 | set xrange [0:24]
46 | set xlabel "Hours"
47 | set ylabel "Avg open time (s)"
48 | plot "${BESTAND}" using 14 linecolor rgb '#77ac30'
49 |
50 | set output '${OUTBESTAND}-maxopen.png'
51 | set style fill solid 0.5
52 | set style data histograms
53 | unset yrange
54 | set xrange [0:24]
55 | set xlabel "Hours"
56 | set ylabel "Max open value"
57 | plot "${BESTAND}" using 16 linecolor rgb '#fde725'
58 | EOF
59 |
60 | exit 0
61 |
--------------------------------------------------------------------------------
/monit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Put to 1 to make this run
4 | ENABLED=1
5 |
6 | THRESHOLD=0.13
7 | GAIN=30
8 | FREQ=446.1e6
9 | RUNTIME=3590
10 | DECIM=10
11 | SAMPRATE=2e6
12 |
13 | # Use the correct tool to run
14 | SPECMON=/home/pi/specmon/specmon_cli.py
15 | #SPECMON=/home/pi/specmon/specmon_cli_pluto.py
16 |
17 | LOGDIR=/tmp
18 |
19 | if [ $ENABLED == 1 ];
20 | then
21 | if [ ! -d $LOGDIR ];
22 | then
23 | mkdir -p $LOGDIR ;
24 | fi
25 |
26 | TIMESTAMP=`date +%y%m%d-%H%M`
27 |
28 |
29 | # Specmon with head-block. quits after a defined period of time. (-R)
30 | stdbuf -oL $SPECMON -T $THRESHOLD -g $GAIN -f $FREQ -s $SAMPRATE -D $DECIM -R $RUNTIME > $LOGDIR/specmon2-$TIMESTAMP.csv 2>> $LOGDIR/specmon.debug
31 |
32 | # The next lines are for temperature and runtime debugging, mainly on a Raspberry Pi
33 | # TEMPLOG=/tmp/specmon2-`date +%y%m%d`.templog
34 | # date >> $TEMPLOG
35 | # Next line only for Raspberry Pi
36 | # /opt/vc/bin/vcgencmd measure_temp >> $TEMPLOG
37 |
38 | fi
39 |
--------------------------------------------------------------------------------
/monit2:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description:
4 | # Wrapper for specmon2 to run from cron
5 | # Auto clean old recordings from /tmp
6 | #
7 | # Author: Bart Somers PE1RIK
8 | #
9 |
10 | # Put to 1 to make this run
11 | ENABLED=1
12 |
13 | # Put to 1 to automatic clean old recordings in /tmp
14 | # Files older than 2 days are removed
15 | AUTOCLEAN=1
16 |
17 | THRESHOLD=10.0
18 | GAIN=40
19 | FREQ=145e6
20 | RUNTIME=3580
21 | DEVICE="rtl=0"
22 | SAMPRATE=2e6
23 | CALVEC=/home/bart/grc/calvec-145M-G40-2048.0.vec
24 | FFTSIZE=2048
25 |
26 | # Use the correct tool to run
27 | SPECMON=/home/bart/grc/specmon2.py
28 |
29 | # Define the logdir
30 | LOGDIR=/home/bart/log/145
31 |
32 | # Start monitoring if enabled.
33 | if [ $ENABLED == 1 ];
34 | then
35 | if [ ! -d $LOGDIR ];
36 | then
37 | mkdir -p $LOGDIR ;
38 | fi
39 |
40 | TIMESTAMP=`date +%y%m%d-%H%M`
41 | echo -e "\nLog started at: ${TIMESTAMP}\n" >> $LOGDIR/specmon2.debug
42 |
43 |
44 | # Specmon with head-block. quits after a defined period of time. (-R)
45 | stdbuf -oL $SPECMON -d $DEVICE -c $CALVEC -T $THRESHOLD -g $GAIN -f $FREQ -s $SAMPRATE -R $RUNTIME -F $FFTSIZE -O $LOGDIR/specmon2-$TIMESTAMP.csv >> $LOGDIR/specmon2.debug 2>&1
46 |
47 | # The next lines are for temperature and runtime debugging, mainly on a Raspberry Pi
48 | # TEMPLOG=/tmp/specmon2-`date +%y%m%d`.templog
49 | # date >> $TEMPLOG
50 | # Next line only for Raspberry Pi
51 | # /opt/vc/bin/vcgencmd measure_temp >> $TEMPLOG
52 |
53 | fi
54 |
55 | # Check to see if autocleaning is enabled.
56 | # Defaults to 2 days old logfiles.
57 | if [ $AUTOCLEAN == 1 ];
58 | then
59 | cleandate=$(date --date="2 days ago" +%y%m%d)
60 | rm -f /tmp/${cleandate}*pvector
61 | fi
62 |
63 | exit 0
64 |
--------------------------------------------------------------------------------
/noisemon/dayboxer:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # 220703 Test boxplot per day
4 | #
5 | #
6 |
7 | OUTDIR="tst"
8 |
9 | if [ ! -d ${OUTDIR} ]; then
10 | mkdir ${OUTDIR}
11 | fi
12 |
13 | if [ -z $1 ] ; then
14 | YESTERDAY=$(date --date=yesterday +%y%m%d)
15 | else
16 | YESTERDAY=$1
17 | echo "Processing day ${YESTERDAY}"
18 | fi
19 |
20 |
21 | # Step 1: Create single value files
22 | for i in noisemon-${YESTERDAY}-{00..23}00.csv;
23 | do
24 | cat $i | cut -d "," -f 3 > ${OUTDIR}/$i
25 | done
26 |
27 | # Step 2: concatenate the files to a single csv
28 | paste -d "," ${OUTDIR}/noisemon-${YESTERDAY}*csv > ${OUTDIR}/${YESTERDAY}.csv
29 |
30 | # Step 3: create the boxplot
31 |
32 | gnuplot <<- EOF
33 | set terminal png size 1280,768
34 | set output '${OUTDIR}/${YESTERDAY}.png'
35 | set datafile separator ","
36 | set style boxplot nooutliers
37 | set style data boxplot
38 | #set boxwidth 0.3
39 | set yrange [-4:0]
40 | plot for [i=1:24] '${OUTDIR}/${YESTERDAY}.csv' using (i):i notitle
41 |
42 |
43 | EOF
44 |
45 | rm ${OUTDIR}/noisemon-${YESTERDAY}*csv
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/noisemon/nmonit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description:
4 | # Wrapper for specmon2 to run from cron
5 | # Auto clean old recordings from /tmp
6 | #
7 | # Author: Bart Somers PE1RIK
8 | #
9 | # ./noisemon.py -f 48e6 -s 2.5e6 -g 12 -F 4096 -c calvec-4096-0.vec -R 120 -d airspy=0 -O /tmp/logfile-dummy-4096-g12.csv
10 |
11 | # Put to 1 to make this run
12 | ENABLED=1
13 |
14 | # Put to 1 to automatic clean old recordings in /tmp
15 | # Files older than 2 days are removed
16 | AUTOCLEAN=1
17 |
18 | GAIN=40
19 | FREQ=145e6
20 | RUNTIME=3580
21 | DEVICE="airspy=0"
22 | SAMPRATE=2e6
23 | #CALVEC=/home/user/noisemon/220911-143M-G40-S2e6-4096-0.calvec
24 | CALVEC=/home/user/noisemon/221014-145M-G40-S2e6-4096-0.calvec
25 | FFTSIZE=4096
26 | SCNLIMIT=3
27 |
28 | # Use the correct tool to run
29 | NOISEMON=/home/user/noisemon/noisemon.py
30 |
31 | # Define the logdir
32 | LOGDIR=/home/user/log/145
33 |
34 | # Start monitoring if enabled.
35 | if [ ${ENABLED} == 1 ];
36 | then
37 | if [ ! -d ${LOGDIR} ];
38 | then
39 | mkdir -p ${LOGDIR} ;
40 | fi
41 |
42 | TIMESTAMP=`date +%y%m%d-%H%M`
43 | echo -e "\nLog started at: ${TIMESTAMP}\n" >> ${LOGDIR}/noisemon.debug
44 |
45 | # Run noisemon with the selected parameters
46 | ${NOISEMON} -f ${FREQ} -s ${SAMPRATE} -F ${FFTSIZE} -g ${GAIN} -c ${CALVEC} -R ${RUNTIME} -d ${DEVICE} -S ${SCNLIMIT} -O ${LOGDIR}/noisemon-${TIMESTAMP}.csv >> ${LOGDIR}/noisemon.debug 2>&1
47 |
48 | # The next lines are for temperature and runtime debugging, mainly on a Raspberry Pi
49 | # TEMPLOG=/tmp/specmon2-`date +%y%m%d`.templog
50 | # date >> $TEMPLOG
51 | # Next line only for Raspberry Pi
52 | # /opt/vc/bin/vcgencmd measure_temp >> $TEMPLOG
53 |
54 | fi
55 |
56 | # Check to see if autocleaning is enabled.
57 | # Defaults to 2 days old logfiles.
58 | if [ $AUTOCLEAN == 1 ];
59 | then
60 | # 2 days
61 | #find /tmp/ -maxdepth 1 -name "*pvector" -mmin +$((2*1440)) -delete
62 | # 1 day
63 | find /tmp/ -maxdepth 1 -name "*pvector" -mmin +1440 -delete
64 | fi
65 |
66 | exit 0
67 |
--------------------------------------------------------------------------------
/noisemon/noisegraph:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description: Wrapper to create daily graphs from parsed logfile
4 | #
5 | # Author: Bart Somers PE1RIK
6 | #
7 |
8 | if [ -z $1 ];
9 | then
10 | echo "Usage: $0 "
11 | exit 1
12 | else
13 |
14 | BESTAND=${1}
15 | fi
16 |
17 |
18 | #OUTBESTAND=${BESTAND}-test
19 | OUTBESTAND=${BESTAND}
20 |
21 | gnuplot <<- EOF
22 | set datafile separator ","
23 | set terminal pngcairo size 1024,768
24 | set output '${OUTBESTAND}-noise.png'
25 | set xlabel "Minutes"
26 | set ylabel "Noise (relative dB)
27 | set xrange [0:60]
28 | plot "${BESTAND}" using (\$4/300):3 skip 3 title "Noise", "${BESTAND}" using (\$4/300):10 skip 3 title "RMS"
29 |
30 | set datafile separator ","
31 | set terminal pngcairo size 1024,768
32 | set output '${OUTBESTAND}-std.png'
33 | set xlabel "Minutes"
34 | set ylabel "STDev noise"
35 | set xrange [0:60]
36 | plot "${BESTAND}" using (\$4/300):8 skip 3 notitle
37 |
38 | set datafile separator ","
39 | set terminal pngcairo size 1024,768
40 | set output '${OUTBESTAND}-diff.png'
41 | set xlabel "Minutes"
42 | set ylabel "Diff Median and Mean"
43 | set xrange [0:60]
44 | #plot "${BESTAND}" using (\$4/300):(\$3-\$7) skip 3 notitle
45 | plot "${BESTAND}" using (\$4/300):12 skip 3 notitle
46 |
47 | set datafile separator ","
48 | set terminal pngcairo size 1024,768
49 | set output '${OUTBESTAND}-skew.png'
50 | set xlabel "Minutes"
51 | set ylabel "Skewness"
52 | set xrange [0:60]
53 | plot "${BESTAND}" using (\$4/300):9 skip 3 notitle
54 |
55 | set datafile separator ","
56 | set terminal pngcairo size 1024,768
57 | set output '${OUTBESTAND}-use-scn.png'
58 | set xlabel "Minutes"
59 | set ylabel "Usage and SCN count"
60 | set xrange [0:60]
61 | plot "${BESTAND}" using (\$4/300):5 skip 3 title "SCN count", "${BESTAND}" using (\$4/300):6 skip 3 title "Normal Usage count"
62 |
63 | set datafile separator ","
64 | set terminal pngcairo size 2048,768
65 | set output '${OUTBESTAND}-combined.png'
66 | set xlabel "Minutes"
67 | set ylabel "combined values"
68 | set xrange [0:60]
69 | plot "${BESTAND}" using (\$4/300):3 skip 3 title "Noise", \
70 | "${BESTAND}" using (\$4/300):8 skip 3 title "STDev", \
71 | "${BESTAND}" using (\$4/300):12 skip 3 title "Diff Mean Median", \
72 | "${BESTAND}" using (\$4/300):9 skip 3 title "Skewness", \
73 | #"${BESTAND}" using (\$4/300):5 skip 3 title "SCN count", \
74 | #"${BESTAND}" using (\$4/300):6 skip 3 title "Normal Usage count"
75 |
76 | EOF
77 |
78 | exit 0
79 |
--------------------------------------------------------------------------------
/noisemon/noisemon.grc:
--------------------------------------------------------------------------------
1 | options:
2 | parameters:
3 | author: PE1RIK
4 | category: '[GRC Hier Blocks]'
5 | cmake_opt: ''
6 | comment: ''
7 | copyright: ''
8 | description: ''
9 | gen_cmake: 'On'
10 | gen_linking: dynamic
11 | generate_options: no_gui
12 | hier_block_src_path: '.:'
13 | id: noisemon
14 | max_nouts: '0'
15 | output_language: python
16 | placement: (0,0)
17 | qt_qss_theme: ''
18 | realtime_scheduling: ''
19 | run: 'True'
20 | run_command: '{python} -u {filename}'
21 | run_options: run
22 | sizing_mode: fixed
23 | thread_safe_setters: ''
24 | title: ''
25 | window_size: ''
26 | states:
27 | bus_sink: false
28 | bus_source: false
29 | bus_structure: null
30 | coordinate: [8, 8]
31 | rotation: 0
32 | state: enabled
33 |
34 | blocks:
35 | - name: fhandler
36 | id: variable
37 | parameters:
38 | comment: ''
39 | value: '0'
40 | states:
41 | bus_sink: false
42 | bus_source: false
43 | bus_structure: null
44 | coordinate: [1232, 164.0]
45 | rotation: 0
46 | state: disabled
47 | - name: intcount
48 | id: variable
49 | parameters:
50 | comment: 'Integration count.
51 |
52 | Also used for normalisation
53 |
54 |
55 | vector_rate is vectors per second
56 |
57 |
58 | intcount = samp_rate/(fftsize * vector_rate)
59 |
60 |
61 | Bij vector_rate = 5 (200ms):
62 |
63 |
64 | intcount = samp_rate/(fftsize * 5)'
65 | value: int(samp_rate/(fftsize * 5))
66 | states:
67 | bus_sink: false
68 | bus_source: false
69 | bus_structure: null
70 | coordinate: [880, 316.0]
71 | rotation: 0
72 | state: enabled
73 | - name: SCNLimit
74 | id: parameter
75 | parameters:
76 | alias: ''
77 | comment: ''
78 | hide: none
79 | label: SCN-Limit
80 | short_id: S
81 | type: intx
82 | value: '3'
83 | states:
84 | bus_sink: false
85 | bus_source: false
86 | bus_structure: null
87 | coordinate: [1008, 32.0]
88 | rotation: 0
89 | state: true
90 | - name: bbgain
91 | id: parameter
92 | parameters:
93 | alias: ''
94 | comment: ''
95 | hide: none
96 | label: BB-Gain
97 | short_id: b
98 | type: intx
99 | value: '30'
100 | states:
101 | bus_sink: false
102 | bus_source: false
103 | bus_structure: null
104 | coordinate: [632, 32]
105 | rotation: 0
106 | state: enabled
107 | - name: blocks_add_xx_0
108 | id: blocks_add_xx
109 | parameters:
110 | affinity: ''
111 | alias: ''
112 | comment: ''
113 | maxoutbuf: '0'
114 | minoutbuf: '0'
115 | num_inputs: '2'
116 | type: float
117 | vlen: fftsize
118 | states:
119 | bus_sink: false
120 | bus_source: false
121 | bus_structure: null
122 | coordinate: [304, 536.0]
123 | rotation: 180
124 | state: enabled
125 | - name: blocks_complex_to_mag_squared_0
126 | id: blocks_complex_to_mag_squared
127 | parameters:
128 | affinity: ''
129 | alias: ''
130 | comment: ''
131 | maxoutbuf: '0'
132 | minoutbuf: '0'
133 | vlen: fftsize
134 | states:
135 | bus_sink: false
136 | bus_source: false
137 | bus_structure: null
138 | coordinate: [1152, 544.0]
139 | rotation: 180
140 | state: enabled
141 | - name: blocks_file_sink_0
142 | id: blocks_file_sink
143 | parameters:
144 | affinity: ''
145 | alias: ''
146 | append: 'False'
147 | comment: 'Debug option to save vector before
148 |
149 | calibration and specmon2 logics'
150 | file: '"/tmp/" + time.strftime("%y%m%d-%H%M") + "-" + str(int(freq)) + "-" + str(int(samp_rate))
151 | + "-" + str(fftsize) + ".pvector"'
152 | type: float
153 | unbuffered: 'False'
154 | vlen: fftsize
155 | states:
156 | bus_sink: false
157 | bus_source: false
158 | bus_structure: null
159 | coordinate: [272, 728.0]
160 | rotation: 180
161 | state: enabled
162 | - name: blocks_file_source_0
163 | id: blocks_file_source
164 | parameters:
165 | affinity: ''
166 | alias: ''
167 | begin_tag: pmt.PMT_NIL
168 | comment: ''
169 | file: calibvec
170 | length: '0'
171 | maxoutbuf: '0'
172 | minoutbuf: '0'
173 | offset: '0'
174 | repeat: 'True'
175 | type: float
176 | vlen: fftsize
177 | states:
178 | bus_sink: false
179 | bus_source: false
180 | bus_structure: null
181 | coordinate: [552, 696.0]
182 | rotation: 180
183 | state: enabled
184 | - name: blocks_head_0
185 | id: blocks_head
186 | parameters:
187 | affinity: ''
188 | alias: ''
189 | comment: ''
190 | maxoutbuf: '0'
191 | minoutbuf: '0'
192 | num_items: int(runtime*samp_rate)
193 | type: complex
194 | vlen: '1'
195 | states:
196 | bus_sink: false
197 | bus_source: false
198 | bus_structure: null
199 | coordinate: [320, 232.0]
200 | rotation: 0
201 | state: enabled
202 | - name: blocks_integrate_xx_0
203 | id: blocks_integrate_xx
204 | parameters:
205 | affinity: ''
206 | alias: ''
207 | comment: ''
208 | decim: intcount
209 | maxoutbuf: '0'
210 | minoutbuf: '0'
211 | type: float
212 | vlen: fftsize
213 | states:
214 | bus_sink: false
215 | bus_source: false
216 | bus_structure: null
217 | coordinate: [960, 536.0]
218 | rotation: 180
219 | state: enabled
220 | - name: blocks_moving_average_xx_0
221 | id: blocks_moving_average_xx
222 | parameters:
223 | affinity: ''
224 | alias: ''
225 | comment: ''
226 | length: '500'
227 | max_iter: '4000'
228 | maxoutbuf: '0'
229 | minoutbuf: '0'
230 | scale: 1.0/500
231 | type: complex
232 | vlen: '1'
233 | states:
234 | bus_sink: false
235 | bus_source: false
236 | bus_structure: null
237 | coordinate: [472, 288.0]
238 | rotation: 0
239 | state: enabled
240 | - name: blocks_multiply_const_vxx_0
241 | id: blocks_multiply_const_vxx
242 | parameters:
243 | affinity: ''
244 | alias: ''
245 | comment: Normalize integrated vectors
246 | const: '[1.0/intcount]*fftsize'
247 | maxoutbuf: '0'
248 | minoutbuf: '0'
249 | type: float
250 | vlen: fftsize
251 | states:
252 | bus_sink: false
253 | bus_source: false
254 | bus_structure: null
255 | coordinate: [736, 536.0]
256 | rotation: 180
257 | state: enabled
258 | - name: blocks_nlog10_ff_0
259 | id: blocks_nlog10_ff
260 | parameters:
261 | affinity: ''
262 | alias: ''
263 | comment: ''
264 | k: '0'
265 | maxoutbuf: '0'
266 | minoutbuf: '0'
267 | n: '10'
268 | vlen: fftsize
269 | states:
270 | bus_sink: false
271 | bus_source: false
272 | bus_structure: null
273 | coordinate: [544, 528.0]
274 | rotation: 180
275 | state: enabled
276 | - name: blocks_stream_to_vector_0
277 | id: blocks_stream_to_vector
278 | parameters:
279 | affinity: ''
280 | alias: ''
281 | comment: ''
282 | maxoutbuf: '0'
283 | minoutbuf: '0'
284 | num_items: fftsize
285 | type: complex
286 | vlen: '1'
287 | states:
288 | bus_sink: false
289 | bus_source: false
290 | bus_structure: null
291 | coordinate: [832, 248]
292 | rotation: 0
293 | state: enabled
294 | - name: blocks_sub_xx_0
295 | id: blocks_sub_xx
296 | parameters:
297 | affinity: ''
298 | alias: ''
299 | comment: ''
300 | maxoutbuf: '0'
301 | minoutbuf: '0'
302 | num_inputs: '2'
303 | type: complex
304 | vlen: '1'
305 | states:
306 | bus_sink: false
307 | bus_source: false
308 | bus_structure: null
309 | coordinate: [656, 224]
310 | rotation: 0
311 | state: enabled
312 | - name: calibvec
313 | id: parameter
314 | parameters:
315 | alias: ''
316 | comment: ''
317 | hide: none
318 | label: Calibration Vector
319 | short_id: c
320 | type: str
321 | value: '0'
322 | states:
323 | bus_sink: false
324 | bus_source: false
325 | bus_structure: null
326 | coordinate: [760, 656.0]
327 | rotation: 0
328 | state: enabled
329 | - name: deviceid
330 | id: parameter
331 | parameters:
332 | alias: ''
333 | comment: ''
334 | hide: none
335 | label: Device ID
336 | short_id: d
337 | type: str
338 | value: '"rtl=00000201"'
339 | states:
340 | bus_sink: false
341 | bus_source: false
342 | bus_structure: null
343 | coordinate: [240, 32]
344 | rotation: 0
345 | state: enabled
346 | - name: fft_vxx_0
347 | id: fft_vxx
348 | parameters:
349 | affinity: ''
350 | alias: ''
351 | comment: ''
352 | fft_size: fftsize
353 | forward: 'True'
354 | maxoutbuf: '0'
355 | minoutbuf: '0'
356 | nthreads: '1'
357 | shift: 'True'
358 | type: complex
359 | window: window.blackmanharris(fftsize)
360 | states:
361 | bus_sink: false
362 | bus_source: false
363 | bus_structure: null
364 | coordinate: [1024, 216]
365 | rotation: 0
366 | state: enabled
367 | - name: fftsize
368 | id: parameter
369 | parameters:
370 | alias: ''
371 | comment: ''
372 | hide: none
373 | label: FFT size
374 | short_id: F
375 | type: intx
376 | value: '1024'
377 | states:
378 | bus_sink: false
379 | bus_source: false
380 | bus_structure: null
381 | coordinate: [944, 656.0]
382 | rotation: 0
383 | state: enabled
384 | - name: freq
385 | id: parameter
386 | parameters:
387 | alias: ''
388 | comment: ''
389 | hide: none
390 | label: Frequency
391 | short_id: f
392 | type: eng_float
393 | value: 145e6
394 | states:
395 | bus_sink: false
396 | bus_source: false
397 | bus_structure: null
398 | coordinate: [392, 32]
399 | rotation: 0
400 | state: enabled
401 | - name: import_0
402 | id: import
403 | parameters:
404 | alias: ''
405 | comment: "Required when not \nusing osmocom source"
406 | imports: import time
407 | states:
408 | bus_sink: false
409 | bus_source: false
410 | bus_structure: null
411 | coordinate: [16, 776.0]
412 | rotation: 0
413 | state: enabled
414 | - name: noisemon_block
415 | id: epy_block
416 | parameters:
417 | SCNLimit: SCNLimit
418 | _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\
419 | \ GRC will instantiate the first class it finds\nto get ports and parameters\
420 | \ of your block. The arguments to __init__ will\nbe the parameters. All of\
421 | \ them are required to have default values!\n\"\"\"\n\nimport numpy as np\n\
422 | from gnuradio import gr\nimport time\nfrom scipy.stats import skew\n\n\nclass\
423 | \ blk(gr.sync_block): # other base classes are basic_block, decim_block, interp_block\n\
424 | \ \"\"\"Noisemon data analysis block. \n This block is the new version\
425 | \ to measure noise levels.\n \n Detect SCN and background noise. No Impulse\
426 | \ Noise yet.\n \"\"\"\n\n\t# Don't use \"logfile\" as varname as it's reserved\
427 | \ in GRC\n #def __init__(self, fftsize=1024, start_state=0, threshold=1.0,\
428 | \ verbose=0, reportfile=\"/tmp/logfile.csv\"): # only default arguments here\n\
429 | \ def __init__(self, fftsize=1024, reportfile=\"/tmp/logfile.csv\", threshold=8.0,\
430 | \ SCNLimit=1): # only default arguments here\n \"\"\"arguments to this\
431 | \ function show up as parameters in GRC\"\"\"\n self.fftsize = fftsize\n\
432 | \ self.reportfile = reportfile\n self.threshold = threshold\n\
433 | \ self.SCNLimit = SCNLimit\n gr.sync_block.__init__(\n \
434 | \ self,\n name='Noisemon', # will show up in GRC\n \
435 | \ in_sig=[(np.float32,fftsize)],\n out_sig=None\n )\n \
436 | \ # Print startline\n self.outfile = open(reportfile, \"a\")\n\
437 | \ print (\"Start,%.2f,Hour,%s,Veclen,%i,Threshold,%.2f,SCNLimit,%i\"\
438 | \ % ( time.time(), str(time.strftime(\"%H\")), self.fftsize, self.threshold,\
439 | \ self.SCNLimit), file=self.outfile, flush=True )\n \n # Print\
440 | \ header\n print (\"N,time,lowlimit,veccount,scncount,nusage,vecmean,vecstd,vecskew,rms,inoise,diff\"\
441 | , file=self.outfile, flush=True)\n # Counter for the number of vectors\n\
442 | \ self.veccount = 0\n # Buffer for the old STDev\n # Start\
443 | \ with high value to prevent first vector as false positive\n # 230514\
444 | \ try an array\n self.oldstdev = []\n \n \n def work(self,\
445 | \ input_items, output_items):\n \n for j in range(len(input_items[0])):\n\
446 | \ if len(input_items[0][j]) == self.fftsize:\n \
447 | \ # Correct length\n \n \
448 | \ # print (\"New Vector\")\n \n \
449 | \ speclist = np.array(input_items[0][j])\n \n \
450 | \ # 220917 trunk the list to the usable value for the Airspy\
451 | \ in 2.5MSps\n # use 0.6, so extract 0.2 on both sides.\n\
452 | \ # See notes on 220917\n # Use\
453 | \ 0.5, so extract 0.25 on both sides.\n # See notes on\
454 | \ 230514\n #trunklist = speclist[(int(self.fftsize*0.25)):(int(self.fftsize-(self.fftsize*0.25)))]\n\
455 | \ #olist = np.sort(trunklist)\n \
456 | \ \n olist = np.sort(speclist)\n \
457 | \ \n # Create a short vector in one place and use\
458 | \ everywhere\n # Use the first 50% for now. ITU-R SM.1753-2\
459 | \ suggest other.\n # Delete the first 10 values, as these\
460 | \ usually hold the DC-spike.\n shortvec = olist[10:(int(len(olist)/2))]\n\
461 | \ \n lowlimit = np.median(shortvec)\n\
462 | \ \n # Stats on the short vector\n\
463 | \ vecmean = np.mean(shortvec)\n \
464 | \ vecstd = np.std(shortvec)\n \n \
465 | \ # Try to detect Impulse Noise\n inoise = 0\n \
466 | \ self.oldstdev.append(vecstd)\n \
467 | \ stdevavg = sum(self.oldstdev)/len(self.oldstdev)\n \
468 | \ #if vecstd > (1.25 * self.oldstdev):\n if vecstd\
469 | \ > (1.25 * stdevavg):\n inoise = 1\n \
470 | \ \n # Update oldstdev\n \
471 | \ #self.oldstdev = vecstd\n if len(self.oldstdev)\
472 | \ > 25:\n del self.oldstdev[0:1]\n \
473 | \ \n # Calculate skewness\n \
474 | \ vecskew = skew(shortvec)\n \n \
475 | \ # Calculate RMS\n b = np.square(shortvec)\n\
476 | \ vecrms = np.sqrt((np.sum(b)/len(b)))\n\n \
477 | \ # Now detect SNC (and normal usage)\n \
478 | \ \n # Create output-vector of lowlimit + threshold\n\
479 | \ #output_items[0][:] = [lowlimit + self.threshold]*self.fftsize\n\
480 | \ \n highcount\
481 | \ = 0\n scncount = 0\n nusage\
482 | \ = 0\n\n for i in speclist:\n \
483 | \ if i < (lowlimit + self.threshold):\n #if\
484 | \ i == 0:\n # Low\n \
485 | \ #print (\"Value is low: \", i, \" Limit: \", (lowlimit + self.threshold)\
486 | \ )\n \n # Now\
487 | \ consider highcounter\n # If highcounter = 0\
488 | \ nothing before\n # If highcounter = 1 consider\
489 | \ SCN\n # If highcounter > 1 consider normal\
490 | \ usage\n \n if\
491 | \ highcount == 0:\n # Nothing before\n \
492 | \ #next\n \
493 | \ pass\n elif highcount <= self.SCNLimit :\n\
494 | \ # We might have SCN\n \
495 | \ #print (\"SCN Detected\")\n \
496 | \ scncount += 1\n elif highcount > self.SCNLimit:\n\
497 | \ # We might have normal usage\n \
498 | \ # print (\"Normal Usage detected. highcount: \"\
499 | , highcount)\n nusage += 1\n \
500 | \ \n # Reset counter\n \
501 | \ highcount = 0\n \
502 | \ \n else:\n # High\n\
503 | \ #print (\"Value is high: \", i, \" Limit: \"\
504 | , (lowlimit + self.threshold) )\n \n \
505 | \ # Increase highcounter \n \
506 | \ highcount += 1\n \
507 | \ \n #print (\"Vectors: \", len(speclist), \" SCN:\
508 | \ \", scncount, \" Normal: \", nusage, \" Low: \", lowlimit, \" Thresh: \",\
509 | \ self.threshold, \" Mean: \", vecmean, \" STD: \", vecstd)\n \
510 | \ #print (\"V: %i L: %i S: %i N: %i L: %.2f T: %.2f M: %.2f std: %.2f\"\
511 | \ % ( len(speclist), self.SCNLimit, scncount, nusage, lowlimit, self.threshold,\
512 | \ vecmean, vecstd ) ) \n # Without veclen, scnlimit,\
513 | \ threshold (in header)\n #print (\"S: %i N: %i L: %.2f\
514 | \ M: %.2f std: %.2f skew: %.2f rms: %.2f\" % ( scncount, nusage, lowlimit, vecmean,\
515 | \ vecstd, vecskew, vecrms ) ) \n\n \n \
516 | \ \n # Debug with vector counter\n \
517 | \ self.veccount+=1\n #print (\"N,%.2f,%.2f,%i\"\
518 | \ % (time.time(), lowlimit, self.veccount), end=\"\\n\", file=self.outfile,\
519 | \ flush=True )\n # N,time,lowlimit,scncount, nusage,vecmean,vecstd,veccount\n\
520 | \ print (\"N,%.2f,%.2f,%i,%i,%i,%.2f,%.2f,%.2f,%.2f,%i,%.2f\"\
521 | \ % (time.time(), lowlimit, self.veccount, scncount, nusage, vecmean, vecstd,\
522 | \ vecskew, vecrms, inoise, abs(lowlimit-vecmean)), end=\"\\n\", file=self.outfile,\
523 | \ flush=True )\n else:\n print (\"Other\
524 | \ length input: \" + str(len(input_items[0][j])))\n \n return\
525 | \ len(input_items[0])\n"
526 | affinity: ''
527 | alias: ''
528 | comment: 'Overal moeten de standaardwaarden gelijk zijn,
529 |
530 | in dit geval dus 4096.
531 |
532 | Pas na compilen kan met een parameter de FFTSIZE veranderd
533 |
534 | worden.'
535 | fftsize: fftsize
536 | maxoutbuf: '0'
537 | minoutbuf: '0'
538 | reportfile: outfile
539 | threshold: threshold
540 | states:
541 | _io_cache: ('Noisemon', 'blk', [('fftsize', '1024'), ('reportfile', "'/tmp/logfile.csv'"),
542 | ('threshold', '8.0'), ('SCNLimit', '1')], [('0', 'float', 1024)], [], 'Noisemon
543 | data analysis block. \n This block is the new version to measure noise levels.\n \n Detect
544 | SCN and background noise. No Impulse Noise yet.\n ', ['SCNLimit', 'fftsize',
545 | 'reportfile', 'threshold'])
546 | bus_sink: false
547 | bus_source: false
548 | bus_structure: null
549 | coordinate: [32, 496.0]
550 | rotation: 180
551 | state: enabled
552 | - name: osmosdr_source_0
553 | id: osmosdr_source
554 | parameters:
555 | affinity: ''
556 | alias: ''
557 | ant0: ''
558 | ant1: ''
559 | ant10: ''
560 | ant11: ''
561 | ant12: ''
562 | ant13: ''
563 | ant14: ''
564 | ant15: ''
565 | ant16: ''
566 | ant17: ''
567 | ant18: ''
568 | ant19: ''
569 | ant2: ''
570 | ant20: ''
571 | ant21: ''
572 | ant22: ''
573 | ant23: ''
574 | ant24: ''
575 | ant25: ''
576 | ant26: ''
577 | ant27: ''
578 | ant28: ''
579 | ant29: ''
580 | ant3: ''
581 | ant30: ''
582 | ant31: ''
583 | ant4: ''
584 | ant5: ''
585 | ant6: ''
586 | ant7: ''
587 | ant8: ''
588 | ant9: ''
589 | args: deviceid
590 | bb_gain0: bbgain
591 | bb_gain1: '20'
592 | bb_gain10: '20'
593 | bb_gain11: '20'
594 | bb_gain12: '20'
595 | bb_gain13: '20'
596 | bb_gain14: '20'
597 | bb_gain15: '20'
598 | bb_gain16: '20'
599 | bb_gain17: '20'
600 | bb_gain18: '20'
601 | bb_gain19: '20'
602 | bb_gain2: '20'
603 | bb_gain20: '20'
604 | bb_gain21: '20'
605 | bb_gain22: '20'
606 | bb_gain23: '20'
607 | bb_gain24: '20'
608 | bb_gain25: '20'
609 | bb_gain26: '20'
610 | bb_gain27: '20'
611 | bb_gain28: '20'
612 | bb_gain29: '20'
613 | bb_gain3: '20'
614 | bb_gain30: '20'
615 | bb_gain31: '20'
616 | bb_gain4: '20'
617 | bb_gain5: '20'
618 | bb_gain6: '20'
619 | bb_gain7: '20'
620 | bb_gain8: '20'
621 | bb_gain9: '20'
622 | bw0: '0'
623 | bw1: '0'
624 | bw10: '0'
625 | bw11: '0'
626 | bw12: '0'
627 | bw13: '0'
628 | bw14: '0'
629 | bw15: '0'
630 | bw16: '0'
631 | bw17: '0'
632 | bw18: '0'
633 | bw19: '0'
634 | bw2: '0'
635 | bw20: '0'
636 | bw21: '0'
637 | bw22: '0'
638 | bw23: '0'
639 | bw24: '0'
640 | bw25: '0'
641 | bw26: '0'
642 | bw27: '0'
643 | bw28: '0'
644 | bw29: '0'
645 | bw3: '0'
646 | bw30: '0'
647 | bw31: '0'
648 | bw4: '0'
649 | bw5: '0'
650 | bw6: '0'
651 | bw7: '0'
652 | bw8: '0'
653 | bw9: '0'
654 | clock_source0: ''
655 | clock_source1: ''
656 | clock_source2: ''
657 | clock_source3: ''
658 | clock_source4: ''
659 | clock_source5: ''
660 | clock_source6: ''
661 | clock_source7: ''
662 | comment: ''
663 | corr0: '0'
664 | corr1: '0'
665 | corr10: '0'
666 | corr11: '0'
667 | corr12: '0'
668 | corr13: '0'
669 | corr14: '0'
670 | corr15: '0'
671 | corr16: '0'
672 | corr17: '0'
673 | corr18: '0'
674 | corr19: '0'
675 | corr2: '0'
676 | corr20: '0'
677 | corr21: '0'
678 | corr22: '0'
679 | corr23: '0'
680 | corr24: '0'
681 | corr25: '0'
682 | corr26: '0'
683 | corr27: '0'
684 | corr28: '0'
685 | corr29: '0'
686 | corr3: '0'
687 | corr30: '0'
688 | corr31: '0'
689 | corr4: '0'
690 | corr5: '0'
691 | corr6: '0'
692 | corr7: '0'
693 | corr8: '0'
694 | corr9: '0'
695 | dc_offset_mode0: '2'
696 | dc_offset_mode1: '0'
697 | dc_offset_mode10: '0'
698 | dc_offset_mode11: '0'
699 | dc_offset_mode12: '0'
700 | dc_offset_mode13: '0'
701 | dc_offset_mode14: '0'
702 | dc_offset_mode15: '0'
703 | dc_offset_mode16: '0'
704 | dc_offset_mode17: '0'
705 | dc_offset_mode18: '0'
706 | dc_offset_mode19: '0'
707 | dc_offset_mode2: '0'
708 | dc_offset_mode20: '0'
709 | dc_offset_mode21: '0'
710 | dc_offset_mode22: '0'
711 | dc_offset_mode23: '0'
712 | dc_offset_mode24: '0'
713 | dc_offset_mode25: '0'
714 | dc_offset_mode26: '0'
715 | dc_offset_mode27: '0'
716 | dc_offset_mode28: '0'
717 | dc_offset_mode29: '0'
718 | dc_offset_mode3: '0'
719 | dc_offset_mode30: '0'
720 | dc_offset_mode31: '0'
721 | dc_offset_mode4: '0'
722 | dc_offset_mode5: '0'
723 | dc_offset_mode6: '0'
724 | dc_offset_mode7: '0'
725 | dc_offset_mode8: '0'
726 | dc_offset_mode9: '0'
727 | freq0: freq
728 | freq1: 100e6
729 | freq10: 100e6
730 | freq11: 100e6
731 | freq12: 100e6
732 | freq13: 100e6
733 | freq14: 100e6
734 | freq15: 100e6
735 | freq16: 100e6
736 | freq17: 100e6
737 | freq18: 100e6
738 | freq19: 100e6
739 | freq2: 100e6
740 | freq20: 100e6
741 | freq21: 100e6
742 | freq22: 100e6
743 | freq23: 100e6
744 | freq24: 100e6
745 | freq25: 100e6
746 | freq26: 100e6
747 | freq27: 100e6
748 | freq28: 100e6
749 | freq29: 100e6
750 | freq3: 100e6
751 | freq30: 100e6
752 | freq31: 100e6
753 | freq4: 100e6
754 | freq5: 100e6
755 | freq6: 100e6
756 | freq7: 100e6
757 | freq8: 100e6
758 | freq9: 100e6
759 | gain0: rfgain
760 | gain1: '10'
761 | gain10: '10'
762 | gain11: '10'
763 | gain12: '10'
764 | gain13: '10'
765 | gain14: '10'
766 | gain15: '10'
767 | gain16: '10'
768 | gain17: '10'
769 | gain18: '10'
770 | gain19: '10'
771 | gain2: '10'
772 | gain20: '10'
773 | gain21: '10'
774 | gain22: '10'
775 | gain23: '10'
776 | gain24: '10'
777 | gain25: '10'
778 | gain26: '10'
779 | gain27: '10'
780 | gain28: '10'
781 | gain29: '10'
782 | gain3: '10'
783 | gain30: '10'
784 | gain31: '10'
785 | gain4: '10'
786 | gain5: '10'
787 | gain6: '10'
788 | gain7: '10'
789 | gain8: '10'
790 | gain9: '10'
791 | gain_mode0: 'False'
792 | gain_mode1: 'False'
793 | gain_mode10: 'False'
794 | gain_mode11: 'False'
795 | gain_mode12: 'False'
796 | gain_mode13: 'False'
797 | gain_mode14: 'False'
798 | gain_mode15: 'False'
799 | gain_mode16: 'False'
800 | gain_mode17: 'False'
801 | gain_mode18: 'False'
802 | gain_mode19: 'False'
803 | gain_mode2: 'False'
804 | gain_mode20: 'False'
805 | gain_mode21: 'False'
806 | gain_mode22: 'False'
807 | gain_mode23: 'False'
808 | gain_mode24: 'False'
809 | gain_mode25: 'False'
810 | gain_mode26: 'False'
811 | gain_mode27: 'False'
812 | gain_mode28: 'False'
813 | gain_mode29: 'False'
814 | gain_mode3: 'False'
815 | gain_mode30: 'False'
816 | gain_mode31: 'False'
817 | gain_mode4: 'False'
818 | gain_mode5: 'False'
819 | gain_mode6: 'False'
820 | gain_mode7: 'False'
821 | gain_mode8: 'False'
822 | gain_mode9: 'False'
823 | if_gain0: '20'
824 | if_gain1: '20'
825 | if_gain10: '20'
826 | if_gain11: '20'
827 | if_gain12: '20'
828 | if_gain13: '20'
829 | if_gain14: '20'
830 | if_gain15: '20'
831 | if_gain16: '20'
832 | if_gain17: '20'
833 | if_gain18: '20'
834 | if_gain19: '20'
835 | if_gain2: '20'
836 | if_gain20: '20'
837 | if_gain21: '20'
838 | if_gain22: '20'
839 | if_gain23: '20'
840 | if_gain24: '20'
841 | if_gain25: '20'
842 | if_gain26: '20'
843 | if_gain27: '20'
844 | if_gain28: '20'
845 | if_gain29: '20'
846 | if_gain3: '20'
847 | if_gain30: '20'
848 | if_gain31: '20'
849 | if_gain4: '20'
850 | if_gain5: '20'
851 | if_gain6: '20'
852 | if_gain7: '20'
853 | if_gain8: '20'
854 | if_gain9: '20'
855 | iq_balance_mode0: '0'
856 | iq_balance_mode1: '0'
857 | iq_balance_mode10: '0'
858 | iq_balance_mode11: '0'
859 | iq_balance_mode12: '0'
860 | iq_balance_mode13: '0'
861 | iq_balance_mode14: '0'
862 | iq_balance_mode15: '0'
863 | iq_balance_mode16: '0'
864 | iq_balance_mode17: '0'
865 | iq_balance_mode18: '0'
866 | iq_balance_mode19: '0'
867 | iq_balance_mode2: '0'
868 | iq_balance_mode20: '0'
869 | iq_balance_mode21: '0'
870 | iq_balance_mode22: '0'
871 | iq_balance_mode23: '0'
872 | iq_balance_mode24: '0'
873 | iq_balance_mode25: '0'
874 | iq_balance_mode26: '0'
875 | iq_balance_mode27: '0'
876 | iq_balance_mode28: '0'
877 | iq_balance_mode29: '0'
878 | iq_balance_mode3: '0'
879 | iq_balance_mode30: '0'
880 | iq_balance_mode31: '0'
881 | iq_balance_mode4: '0'
882 | iq_balance_mode5: '0'
883 | iq_balance_mode6: '0'
884 | iq_balance_mode7: '0'
885 | iq_balance_mode8: '0'
886 | iq_balance_mode9: '0'
887 | maxoutbuf: '0'
888 | minoutbuf: '0'
889 | nchan: '1'
890 | num_mboards: '1'
891 | sample_rate: samp_rate
892 | sync: sync
893 | time_source0: ''
894 | time_source1: ''
895 | time_source2: ''
896 | time_source3: ''
897 | time_source4: ''
898 | time_source5: ''
899 | time_source6: ''
900 | time_source7: ''
901 | type: fc32
902 | states:
903 | bus_sink: false
904 | bus_source: false
905 | bus_structure: null
906 | coordinate: [16, 236.0]
907 | rotation: 0
908 | state: enabled
909 | - name: outfile
910 | id: parameter
911 | parameters:
912 | alias: ''
913 | comment: ''
914 | hide: none
915 | label: Output File
916 | short_id: O
917 | type: str
918 | value: '"/tmp/logfile.csv"'
919 | states:
920 | bus_sink: false
921 | bus_source: false
922 | bus_structure: null
923 | coordinate: [1192, 36.0]
924 | rotation: 0
925 | state: true
926 | - name: rfgain
927 | id: parameter
928 | parameters:
929 | alias: ''
930 | comment: ''
931 | hide: none
932 | label: RF-Gain
933 | short_id: g
934 | type: intx
935 | value: '40'
936 | states:
937 | bus_sink: false
938 | bus_source: false
939 | bus_structure: null
940 | coordinate: [520, 32]
941 | rotation: 0
942 | state: enabled
943 | - name: runtime
944 | id: parameter
945 | parameters:
946 | alias: ''
947 | comment: ''
948 | hide: none
949 | label: ''
950 | short_id: R
951 | type: intx
952 | value: '3590'
953 | states:
954 | bus_sink: false
955 | bus_source: false
956 | bus_structure: null
957 | coordinate: [320, 328.0]
958 | rotation: 0
959 | state: enabled
960 | - name: samp_rate
961 | id: parameter
962 | parameters:
963 | alias: ''
964 | comment: ''
965 | hide: none
966 | label: Sample Rate
967 | short_id: s
968 | type: eng_float
969 | value: 2e6
970 | states:
971 | bus_sink: false
972 | bus_source: false
973 | bus_structure: null
974 | coordinate: [872, 32]
975 | rotation: 0
976 | state: enabled
977 | - name: threshold
978 | id: parameter
979 | parameters:
980 | alias: ''
981 | comment: ''
982 | hide: none
983 | label: Threshold
984 | short_id: T
985 | type: eng_float
986 | value: '8.0'
987 | states:
988 | bus_sink: false
989 | bus_source: false
990 | bus_structure: null
991 | coordinate: [752, 32]
992 | rotation: 0
993 | state: enabled
994 | - name: zeromq_pub_sink_0
995 | id: zeromq_pub_sink
996 | parameters:
997 | address: tcp://*:50001
998 | affinity: ''
999 | alias: ''
1000 | comment: ''
1001 | hwm: '-1'
1002 | pass_tags: 'False'
1003 | timeout: '100'
1004 | type: float
1005 | vlen: fftsize
1006 | states:
1007 | bus_sink: false
1008 | bus_source: false
1009 | bus_structure: null
1010 | coordinate: [40, 656.0]
1011 | rotation: 180
1012 | state: true
1013 |
1014 | connections:
1015 | - [blocks_add_xx_0, '0', noisemon_block, '0']
1016 | - [blocks_add_xx_0, '0', zeromq_pub_sink_0, '0']
1017 | - [blocks_complex_to_mag_squared_0, '0', blocks_integrate_xx_0, '0']
1018 | - [blocks_file_source_0, '0', blocks_add_xx_0, '1']
1019 | - [blocks_head_0, '0', blocks_moving_average_xx_0, '0']
1020 | - [blocks_head_0, '0', blocks_sub_xx_0, '0']
1021 | - [blocks_integrate_xx_0, '0', blocks_multiply_const_vxx_0, '0']
1022 | - [blocks_moving_average_xx_0, '0', blocks_sub_xx_0, '1']
1023 | - [blocks_multiply_const_vxx_0, '0', blocks_nlog10_ff_0, '0']
1024 | - [blocks_nlog10_ff_0, '0', blocks_add_xx_0, '0']
1025 | - [blocks_nlog10_ff_0, '0', blocks_file_sink_0, '0']
1026 | - [blocks_stream_to_vector_0, '0', fft_vxx_0, '0']
1027 | - [blocks_sub_xx_0, '0', blocks_stream_to_vector_0, '0']
1028 | - [fft_vxx_0, '0', blocks_complex_to_mag_squared_0, '0']
1029 | - [osmosdr_source_0, '0', blocks_head_0, '0']
1030 |
1031 | metadata:
1032 | file_format: 1
1033 |
--------------------------------------------------------------------------------
/noisemon/readme.md:
--------------------------------------------------------------------------------
1 | # Noisemon
2 | Noisemon is a rewrite of specmon, with the goal to measure noiselevels.
3 | The definition of noisemeasurements is stated in ITU documents, ITU-P SM.372-16, ITU-R SM.2055 and specific SM.1753-2.
4 | Based upon the above mentioned documents, multiple types of noise are identified:
5 |
6 | - WGN, or White Gaussian Noise
7 | - SCN, or Single Carrier Noise
8 | - IN, or Impulse Noise
9 |
10 | Besides identification of noise-types, normal usage of the frequency band is identified, based upon the assumption of minimum bandwidth for transmissions, as described in the ITU documents.
11 |
12 | The use of noisemon is to measure and display several types of noise over a long period of time. Measurements are taken every 200ms, or five times per second.
13 |
14 | ## Preparation
15 | The preparation for noisemon measurements is equal to setting up measurements with Specmon.
16 |
17 | ### RBW
18 | According to the ITU documentation for noise measurements, the RBW should be 500Hz or less. Using this RBW, Single Carrier Noise can be identified, based on the FFT's active on the detected signal.
19 | Using 2MSps and thus monitoring 2MHz of bandwidth, this requires an FFT-size of 4096. This yields to an RBW of 488Hz.
20 | When very smallband transmissions are expected, the FFT-size must be increased.
21 |
22 | ### Filtering
23 | When insufficient filtering is applied, spurious signals can be seen in the spectrum. This results in false measurements of SCN. Strong nearby signals can increase the overall noisefloor. If the selected SDR features analogue low-pass filters, it is advised to apply them. Not all SDR's have them but the PlutoSDR and LimeSDR Mini are two SDR with this features.
24 |
25 |
26 | ### Determine the threshold
27 | The threshold is the powerlevel value which a transmission should reach before it is considered as a transmission. According to the ITU it should be 20dB above the noise level however this is a high limit for relative low power transmissions or weak transmissions, caused by a higher free-space path loss. These latter transmissions are not recorded as transmissions with a high threshold. Using a low threshold on the other hand will cause false positives due to short term impulses, caused by RFI or noisefloor variances.
28 | The threshold can be controlled either afterwards using a replay from previous monitoring or by inspecting the measurements using specreceive.
29 | The default dynamic threshold is set to 8dB above the median noise level.
30 |
31 | ### SCN Limit
32 | An experimental option is available in noisemon. Detecting Single Carrier Noise is achieved by measuring the amount of adjacent FFT-bins above the threshold. SCN should only activate one FFT-bin but due to FFT-leakage, for example caused by the carrier not being in the middle of the FFT-bin, more FFT-bins can be activated. Some experiments show that 3 FFT's is a reasonable value, if the FFT-size is 500Hz or less. This 500Hz limit is defined by the ITU.
33 |
34 | ## Monitoring
35 | The monitoring is setup via cron using the tool `nmonit`.
36 | Edit nmonit with the required settings:
37 |
38 | ````
39 | # Put to 1 to make this run
40 | ENABLED=1
41 |
42 | # Put to 1 to automatic clean old recordings in /tmp
43 | # Files older than 2 days are removed
44 | AUTOCLEAN=1
45 |
46 | GAIN=40
47 | FREQ=145e6
48 | RUNTIME=3580
49 | DEVICE="airspy=0"
50 | SAMPRATE=2e6
51 | #CALVEC=/home/user/noisemon/220911-143M-G40-S2e6-4096-0.calvec
52 | CALVEC=/home/user/noisemon/221014-145M-G40-S2e6-4096-0.calvec
53 | FFTSIZE=4096
54 | SCNLIMIT=3
55 |
56 | # Use the correct tool to run
57 | NOISEMON=/home/user/noisemon/noisemon.py
58 |
59 | # Define the logdir
60 | LOGDIR=/home/user/log/145
61 | ````
62 |
63 |
64 | Please be aware of the runtime. It defaults to 3590 seconds instead of 3600 seconds. Starting and stopping the measurement takes some seconds, as the SDR needs to be initialized. Running the tool with 3600 results in running just over an hour and preventing the next hour to start the measurement.
65 |
66 |
67 | Run monit via cron:
68 |
69 | `0 * * * * /home/user/specmon/nmonit`
70 |
71 | ## Postprocessing
72 | Postprocessing on the logfiles can be executed manual or via cron.
73 |
74 | ### Noisegraph
75 | Manual creation of the graphs can be done using:
76 |
77 | ````
78 | for i in noisemon-YYMMDD-{00..23}00.csv; do ./noisegraph ; done
79 | ````
80 |
81 | This creates multiple graphs from the measurements:
82 |
83 | 1. `noisemon-YYMMDD-HHMM.csv-combined.png` Combined graph with noiselevel, Standard deviation of the noise, difference between mean and median and skewness of the noise.
84 | 2. `noisemon-YYMMDD-HHMM.csv-diff.png` Graph with the difference between the median and the mean of the measured noise.
85 | 3. `noisemon-YYMMDD-HHMM.csv-noise.png` Graph with the measured noise.
86 | 4. `noisemon-YYMMDD-HHMM.csv-skew.png` Graph with the skewness of the measured noise.
87 | 5. `noisemon-YYMMDD-HHMM.csv-std.png` Graph with the standard deviation of the measured noise.
88 | 6. `noisemon-YYMMDD-HHMM.csv-use-scn.png` Graph with the amount of normal usage and Single Carrier Noise, as calculated.
89 |
90 |
91 | ### Dayboxer
92 | Using the script `dayboxer` a graph is made with boxplots of the measured noise. This graph hold 24 boxplots and shows the spreading of the noise over the day.
93 | Dayboxer default print graphs from "yesterday" but other dates can be processed:
94 |
95 | `./dayboxer YYMMDD`
96 |
97 | Dayboxer default writes the graphs to the directory `tst/` in the current directory. This can be modified in the script.
98 |
99 | ## Data format
100 | The logfiles from noisemon are written to the log directory as configured in the nmonit wrapper.
101 | Data in this files are stored as csv, comma separated values. The format of the file is as follows:
102 |
103 | ````
104 | Start,1667473204.96,Hour,12,Veclen,4096,Threshold,8.00,SCNLimit,3
105 | N,time,lowlimit,veccount,scncount,nusage,vecmean,vecstd,vecskew,rms,inoise,diff
106 | N,1667473207.47,8.56,1,8,4,8.48,0.44,-1.51,8.49,0,0.12
107 | N,1667473207.64,8.66,2,8,4,8.58,0.40,-1.10,8.59,0,0.12
108 | ````
109 |
110 | The first line is the Start line. This writes:
111 |
112 | 1. The starting time in unix timestamp
113 | 2. Hour: The hour in which the measurement is started
114 | 3. Veclen: Used FFT-size (length of the vector)
115 | 4. Threshold: Threshold value above the noise. Adopted when the noiselevel changes
116 | 5. SCNLimit: Amount of FFT-bin's which can count as SCN. More than this is counted as normal usage
117 |
118 | The second line is the dataformat of the measured values. All values are calculated on a subset of the entire vector, named noisevector:
119 |
120 | 1. N: Noisemon
121 | 2. time: Time of the measurement in Unix timestamp
122 | 3. lowlimit: The median of the noisevector. The threshold is determined on this value
123 | 4. veccount: Count of measurements in this run
124 | 5. scncount: Counted SCN spikes
125 | 6. nusage: Counted "Normal usage" (wider than SCN)
126 | 7. vecmean: Mean of the noisevector.
127 | 8. vecstd: Standard Deviation in the noisevector.
128 | 9. vecskew: Skewness of the noisevector.
129 | 10. rms: RMS value of the noisevector.
130 | 11. inoise: Value for the (experimental) detection of Impulse Noise. 1 for INoise
131 | 12. diff: Absolute difference between the median(lowlimit) and mean(vecmean)
132 |
133 |
--------------------------------------------------------------------------------
/parselog:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Description: Wrapper to automate the parsing of the individual logfiles to
4 | # combined daily logs
5 | #
6 | # Author: Bart Somers PE1RIK
7 | #
8 |
9 | LOGDIR=/home/pi/log
10 | DATESTRING=`date --date=yesterday +%y%m%d`
11 | OUTSTRING=`date +%y%m%d`
12 | LOGPREFIX=specmon2
13 | ENABLED=1
14 | TESTSPEC=/home/pi/specmon/testspec
15 | MKGRAPH=/home/pi/specmon/mkgraph
16 |
17 | if [ ${ENABLED} == 1 ]; then
18 | for i in `ls ${LOGDIR}/${LOGPREFIX}-${DATESTRING}*csv`; do
19 |
20 | ${TESTSPEC} -i $i -o ${LOGDIR}/${DATESTRING}.plot;
21 | done
22 |
23 | ${MKGRAPH} ${LOGDIR}/${DATESTRING}.plot
24 |
25 | fi
26 |
27 |
28 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Specmon 2
2 | Specmon 2 is a rewrite of the original Specmon, version 1.
3 | The goal of this project is to enable **Spec**trum **Mon**itoring over a long period of time while logging short-term activities.
4 | Using this combined logging over time it is possible to generate statistical usage over time.
5 | When plotting these results, usage statistics and usage patterns becomes visible.
6 |
7 | ## Requirements
8 | Specmon is based on SDR techniques. A suitable Software Defined Radio receiver is required to run the software. As Specmon is written in GNURadio, all the supported SDR's are usable with this software.
9 | Besides the SDR, an antenna for the spectrum under investigation is required.
10 | As most SDR's lack good frontend-filtering, bandfiltering is required to maintain reliable results.
11 |
12 | ### Dependencies
13 | Specmon is build upon GNURadio, Python and Gnuplot.
14 | For Debian-based systems the dependencies can be installed with:
15 |
16 | `apt install gnuradio gr-osmosdr python-pil rtl-sdr python3-scipy python3-numpy python3-matplotlib csvkit paste gnuplot`
17 |
18 | For support for other SDR's, install the required modules. For example for PlutoSDR:
19 |
20 | `apt install libiio0 libad9361-0 gr-iio`
21 |
22 | When using another SDR than the supported radio's under OsmoSDR, modify the flowgraph accordingly.
23 |
24 | ## Preparation
25 | Several steps are required to run specmon2:
26 |
27 | 1. Define the frequency band to monitor. For example: 2M HAM band, 144-146 MHz
28 | 2. Define the required sample-rate. In this case 2Msps.
29 | 3. Select the minimum frequency-size to trigger on: In this case FT8 as smallband mode needs to trigger the measurement. Using an FFT-size of 2048 results in a minimum monitoring of approx 1KHz (976Hz)
30 | 4. Calibrate the receiver and create a calibration vector for the measurement. The process of calibration is described seperately.
31 | 5. Determine the threshold for the measurement using live monitoring.
32 | 6. Setup the monitoring
33 |
34 | The gain settings of your SDR are highly dependent on the local environment and the antenna. Please use a low to moderate gain setting and use bandfilters to prevent overloading or images by out of band signals.
35 |
36 | ## Calibration
37 | Calibration is the process of alignment of the spectrum to the same value: That is, correcting the vector of FFT's to the same baseline. This generates a "flat spectrum". With this flat spectrum a single threshold value can be used during the monitoring process.
38 |
39 | Steps to take (in this order):
40 |
41 | ### Zero vector
42 | Create a "zero" vector with the correct FFT-size and a constant value of zero:
43 |
44 | `./calvec -o zero-calvec-2048.vec -l 2048 -c 0`
45 |
46 | This generates a file named zero-calvec-2048.vec with a "zero calibration" vector to use in the process.
47 |
48 | ### Dummy load measurement
49 | Connect the SDR to a dummyload to run this step. This is required as this corrects the spectrum.
50 | Run specmon2 for a minute with the required settings and record the vectors. These vectors are used to create the final calibration-vector:
51 |
52 | `./specmon2.py -g 20 -f 145e6 -s 2e6 -c zero-calvec-2048.vec -F 2048 -d rtl=0 -R 60`
53 |
54 | Setting the threshold is not required yet.
55 |
56 | ### Create the calibration vector
57 | From the output, written in /tmp on the filesystem, generate the calibration vector:
58 |
59 | `./calvec -i /tmp/210512-0641-145000000-2000000-2048.pvector -o 210521-145e6-2e6-2048-2.vec -l 2048 -c 2`
60 |
61 | This generates a calibration-vector:
62 |
63 | - With length 2048
64 | - With a constant 2 added to the values (lifting the spectrum)
65 | - Created on May 21th 2021 06:41
66 | - For frequency 145MHz
67 | - And samplerate 2Msps
68 |
69 | This calibration-vector is used for the monitoring process
70 |
71 | ### Determine the threshold
72 | The threshold is the powerlevel value which a transmission should reach before it is considered as a transmission. According to the ITU it should be 20dB above the noise level however this is a high limit for relative low power transmissions or weak transmissions, caused by a higher free-space path loss. These latter transmissions are not recorded as transmissions with a high threshold. Using a low threshold on the other hand will cause false positives due to short term impulses, caused by RFI or noisefloor variances.
73 | The threshold can be controlled either afterwards using a replay from previous monitoring or by inspecting the measurements using specmon_gui.
74 |
75 | #### Auto Threshold calculation
76 | Specmon2 is capable of adjusting the threshold value, based on the variances in the measured noise. The value passed to the parameter "threshold" is considered as the value above the measured noise level. During the monitoring process the actual threshold is adopted and printed in the raw measurement files.
77 |
78 | ## Monitoring
79 | The monitoring is setup via cron using the tool `monit2`.
80 | Edit monit2 with the required settings:
81 |
82 | ````
83 | # Put to 1 to make this run
84 | ENABLED=1
85 |
86 | # Put to 1 to automatic clean old recordings in /tmp
87 | # Files older than 2 days are removed
88 | AUTOCLEAN=1
89 |
90 | THRESHOLD=8.0
91 | GAIN=20
92 | FREQ=145e6
93 | RUNTIME=3590
94 | DEVICE="rtl=0"
95 | SAMPRATE=2e6
96 | CALVEC=/home/pi/specmon/210504-calvec-145M-2e6-2048-0.vec
97 | FFTSIZE=2048
98 |
99 | # Use the correct tool to run
100 | SPECMON=/home/pi/specmon/specmon2.py
101 |
102 | LOGDIR=/home/pi/log/145
103 | ````
104 | Please be aware of the runtime. It defaults to 3590 seconds instead of 3600 seconds. Starting and stopping the measurement takes some seconds, as the SDR needs to be initialized. Running the tool with 3600 results in running just over an hour and preventing the next hour to start the measurement.
105 |
106 |
107 | Run monit via cron:
108 |
109 | `0 * * * * /home/pi/specmon/monit2`
110 |
111 | ## Postprocessing
112 | Postprocessing the logfiles can be automated with `parselog`.
113 | Check the settings in this file and run via cron:
114 |
115 | `0 1 * * * /home/pi/specmon/parselog`
116 |
117 | This needs to run only once a day and will generate the graphs for the previous day:
118 |
119 | 1. `YYMMDD.plot-avgopen.png` : Average time in seconds above the threshold.
120 | 2. `YYMMDD.plot-maxopen.png` : Maximum measured value above the threshold.
121 | 3. `YYMMDD.plot-opening.png` : Number of times the threshold is triggered.
122 | 4. `YYMMDD.plot-percent.png` : Percentage of time the threshold is triggered.
123 |
124 | ### Weekly or monthly graphs
125 | Weekly or monthly graphs can manually be made by combine the daily logs to one large file:
126 |
127 | `cat 2105*.plot >> May2021.plot`
128 | And create a monthly graph with mgraph:
129 |
130 | `./mgraph May2021.plot`
131 |
132 | ## Specmon GUI
133 | Specmon2 can run graphical with `specmon2_gui`. This does not log all the output but the spectrum and the vectors of the flattend spectrum are displayed, together with the threshold.
134 | Specmon2_gui can be used to inspect the spectrum and select the right constant for the calibration-vector.
135 |
136 | ## Live view of data
137 | During the monitoring process, it is possible to connect to the ZMQ port for live view of the data, that are the vectors to be processed by specmon, remotely.
138 | For this a tool is added, specreceive, which can connect to the ZMQ port 50001, on the system, running specmon.
139 | As this only sends the integrated vectors, the amount is data is fairly low and can be send over a VPN or remote connection.
140 |
141 | ### Specreceive display
142 | Specreceive has two main displays:
143 | The first display, in the tab Spectrum, the current spectrum view is displayed.
144 | In addition to the spectrum, two more lines are drwan:
145 |
146 | 1. The green line is the "sorted spectrum", that is sorting the vector from low to high.
147 | 2. Based on the median of the lower half of the sorted spectrum (green line) the threshold is calculated.
148 |
149 | The second display is a waterfall display of the spectrum.
150 |
151 | ## Replay of recorded data
152 | The unprocessed vectors from the measurements are stored in /tmp. The vectors are not corrected yet with the calibration vector and thus named "unprocessed". These files can be graphical replayed, together with the calibration-vector to review the state while recorded. This can show RFI or other unknown transmissions, or can be used to modify the threshold value.
153 |
154 | ## Tools overview
155 | The following tools are included in this toolkit:
156 |
157 | ### specmon2
158 | The commandline tool for long term monitoring
159 |
160 | #### Options
161 |
162 | ````
163 | usage: specmon2.py [-h] [-b BBGAIN] [-c CALIBVEC] [-d DEVICEID] [-F FFTSIZE] [-f FREQ] [-O OUTFILE] [-g RFGAIN] [-R RUNTIME]
164 | [-s SAMP_RATE] [-T THRESHOLD] [-v VERBOSE]
165 |
166 | optional arguments:
167 | -h, --help show this help message and exit
168 | -b BBGAIN, --bbgain BBGAIN
169 | Set BB-Gain [default=30]
170 | -c CALIBVEC, --calibvec CALIBVEC
171 | Set Calibration Vector [default='0']
172 | -d DEVICEID, --deviceid DEVICEID
173 | Set Device ID [default='rtl=00000201']
174 | -F FFTSIZE, --fftsize FFTSIZE
175 | Set FFT size [default=1024]
176 | -f FREQ, --freq FREQ Set Frequency [default='145.0M']
177 | -O OUTFILE, --outfile OUTFILE
178 | Set Output File [default='/tmp/logfile.csv']
179 | -g RFGAIN, --rfgain RFGAIN
180 | Set RF-Gain [default=40]
181 | -R RUNTIME, --runtime RUNTIME
182 | Set runtime [default=3590]
183 | -s SAMP_RATE, --samp-rate SAMP_RATE
184 | Set Sample Rate [default='2.0M']
185 | -T THRESHOLD, --threshold THRESHOLD
186 | Set Threshold [default='100.0m']
187 | -v VERBOSE, --verbose VERBOSE
188 | Set Print verbose values [default=0]
189 | ````
190 |
191 | ### Specmon2_gui
192 | Specmon2 but with graphical display. To be used for manual monitoring and tuning of parameters
193 |
194 | #### Options
195 |
196 | ````
197 | usage: specmon2_gui.py [-h] [-b BBGAIN] [-c CALIBVEC] [-d DEVICEID] [-F FFTSIZE] [-O OUTFILE] [-R RUNTIME] [-s SAMP_RATE]
198 | [-v VERBOSE]
199 |
200 | optional arguments:
201 | -h, --help show this help message and exit
202 | -b BBGAIN, --bbgain BBGAIN
203 | Set BB-Gain [default=30]
204 | -c CALIBVEC, --calibvec CALIBVEC
205 | Set Calibration Vector [default='/home/bart/grc/210926-zero-2048.vec']
206 | -d DEVICEID, --deviceid DEVICEID
207 | Set Device ID [default='rtl=0']
208 | -F FFTSIZE, --fftsize FFTSIZE
209 | Set FFT size [default=1024]
210 | -O OUTFILE, --outfile OUTFILE
211 | Set Output File [default='/tmp/logfile.csv']
212 | -R RUNTIME, --runtime RUNTIME
213 | Set runtime [default=3590]
214 | -s SAMP_RATE, --samp-rate SAMP_RATE
215 | Set Sample Rate [default='2.0M']
216 | -v VERBOSE, --verbose VERBOSE
217 | Set Print verbose values [default=0]
218 | ````
219 |
220 | ### calvec
221 | Tool to create calibration vector, based on real measurement-data or a constant vector.
222 |
223 | #### Options
224 |
225 | ````
226 | usage: calvec [-h] [-i INFILE] -o OUTFILE -c CONSTANT -l LENGTH
227 |
228 | optional arguments:
229 | -h, --help show this help message and exit
230 | -i INFILE, --infile INFILE
231 | Filename with vectors
232 | -o OUTFILE, --outfile OUTFILE
233 | Filename where to put output
234 | -c CONSTANT, --constant CONSTANT
235 | Constant to use for calculation
236 | -l LENGTH, --length LENGTH
237 | Vector-length to parse
238 |
239 | ````
240 |
241 | ### mkgraph
242 | This tool is used to create the graphs from the parsed data.
243 | Usage: `./mkgraph `
244 |
245 | ### monit2
246 | Shellscript to automate monitoring and cleanup from old loggings. The usage of monit2 is described above
247 |
248 | ### mgraph
249 | Shellscript to generate the monthly-graph from the concatenated logfiles.
250 | Usage: `./mgraph `
251 |
252 | ### parselog
253 | Shellscript to automate the parsing of logfiles and creation of the graphs. To be run from cron so no options required.
254 | See the shellscript for the correct paths.
255 |
256 | ### testspec
257 | This is the parser for the logfiles from specmon2. It is called from parselog but can be used manually too.
258 |
259 | #### Options
260 |
261 | ````
262 | usage: calvec [-h] [-i INFILE] -o OUTFILE -c CONSTANT -l LENGTH
263 |
264 | optional arguments:
265 | -h, --help show this help message and exit
266 | -i INFILE, --infile INFILE
267 | Filename with vectors
268 | -o OUTFILE, --outfile OUTFILE
269 | Filename where to put output
270 | -c CONSTANT, --constant CONSTANT
271 | Constant to use for calculation
272 | -l LENGTH, --length LENGTH
273 | Vector-length to parse
274 |
275 | ````
276 |
277 | ### specreceive
278 | This is the ZMQ receiver for live remote view.
279 | Specreceive does not have commandline options but the flowgraph holds multiple variables which need to be set before running the flowgrapgh.
280 | The options required to correct are:
281 |
282 | - FFT size
283 | - Frequency
284 | - Sample Rate
285 | - Hostname or IP to connect to, in the ZMQ source block.
286 | + This should be in the format: `tcp://:50001`
287 |
288 | Specreceive also shows a line representing the threshold, which can be set manually using the slider.
289 |
290 | #### Options
291 |
292 | ````
293 | usage: specreceive.py [-h] [-c CALCONST] [-F FFTSIZE] [-f FREQ] [-r REMOTE] [-s SAMP_RATE]
294 |
295 | optional arguments:
296 | -h, --help show this help message and exit
297 | -c CALCONST, --calconst CALCONST
298 | Set calibration-constant [default='-132.0']
299 | -F FFTSIZE, --fftsize FFTSIZE
300 | Set fft-size [default=4096]
301 | -f FREQ, --freq FREQ Set Frequency [default='48.0M']
302 | -r REMOTE, --remote REMOTE
303 | Set remote-host [default='tcp://remote:50001']
304 | -s SAMP_RATE, --samp-rate SAMP_RATE
305 | Set Sample-Rate [default='2.5M']
306 | ````
307 |
308 | ## Usage suggestions
309 | Below are some suggestions to use the software. These suggestions are focused on the HAM-radio bands but probably other bands can monitored too.
310 |
311 | ### 2M HAM band
312 |
313 | - Frequency : 144 - 146 MHz
314 | - Tuner frequency: 145e6
315 | - Sample rate : 2e6
316 | - FFT-size: 2048 / 4096
317 |
318 | ### 6M HAM band
319 |
320 | - Frequency : 50 - 52 MHz
321 | - Tuner frequency : 51e6
322 | - Sample rate : 2e6
323 | - FFT-size : 2048 / 4096
324 |
325 | ### 70cm HAM band
326 | This band is 10MHz wide. The sample-rate must be supported by your SDR. A LimeSDR mini or Airspy R2 support this. This combination of sample rate and FFT-size is likely too much for a Raspberry Pi.
327 |
328 | - Frequency : 430 - 440 MHz
329 | - Tuner frequency : 435e6
330 | - Sample rate : 10e6
331 | - FFT-size : 16384
332 |
333 | ### EU 868MHz ISM band
334 | This band is wider than the suggested 2.5MHz but it holds the majority of the LoRa frequencies. Using this settings, the IOT usage can be monitored. As the LoRa transmissions are at least 125KHz wide, the FFT-size is sufficient for this monitoring.
335 |
336 | - Tuner frequency : 868.35MHz
337 | - Sample rate : 2.5e6
338 | - FFT-size : 2048
339 |
340 |
--------------------------------------------------------------------------------
/specmon-v1.md:
--------------------------------------------------------------------------------
1 | # SPECMON
2 |
3 | Specmon is a set of tools for statistical **spec**trum **mon**itoring. It's designed for long-term monitoring and reporting usage statistics for the selected frequency-range.
4 | Specmon is not capable of recording transmissions in any way.
5 |
6 |
7 | ## The software
8 | The main tool is written in GNUradio [[5]]. Postprocessing is done in Python and graphs are plotted in GNUplot. The platforms used are Debian 10 and Raspbian 10.
9 | When running headless on a Raspberry Pi, a Raspberry Pi 3 or better is required.
10 |
11 | ### Dependencies
12 |
13 | `apt install gnuradio gnuplot gr-osmosdr`
14 | This dependencies allows you to use [RTL-SDR] , [HackRF], and [BladeRF]. If you need support for your specific SDR, you need to install the dependencies too.
If you need support for [PlutoSDR], you need to install the next dependencies:
15 | `apt install libiio0 libad9361-0 gr-iio`
16 |
17 | The default palette for the graphs can be changed by loading an additional palette from [gnuplot-palettes]. The weekgraphs are made with 'reds.pal'
18 |
19 | ## Running the software
20 |
21 | Running the software is quite easy but requires some preparations:
22 |
23 | 1. Choose the frequency to be monitored
24 | 2. Determine the required bandwidth, sample-rate and decimation
25 | - This defines the centre-frequency, or frequency to tune the SDR to.
26 | 3. Determine the threshold
27 | 4. Select the time to run. Default is 3590 seconds.
28 |
29 | The default runtime is 10 seconds less than one hour. This is to prevent the software is starting up again while just finishing the last measurement.
30 |
31 | ### Example
32 |
33 | We want to monitor the European PMR (Public Mobile Radio) band [[4]]. The defined frequency-range is 446.0 - 446.2 MHz so 200KHz bandwith.
34 | The center-frequency is 446.1MHz. You need to tune the SDR to this frequency.
35 | The required sample-rate should be 200.000 samples per second (200ksps). With the decimation-option this samplerate is created: Sample-rate 2Msps and a decimation 10 results in exactly 200.000 samples per second.
36 |
37 | I advice you to first run the GUI version to visual inspect the selected spectrum and to determine the threshold. From within Gnuradio-Companion, run specmon.grc, select the frequency (446.1e6), sample-rate (2e6), decimation (10) and run the flowchart.
38 |
39 | All depending on your SDR, gain, antenna and environment you can see the threshold drop when the frequency-band is idle. Take note of this value and increase it a little bit. For example, if it's idling around 0.75, increase to about 0.9 to prevent false-positives but prevent missing-out some band-usage.
40 |
41 | ### Running the software headless
42 |
43 | Specmon is designed to run one hour and restart for a new logfile. The previous logfile can be postprocessed and converted to a graph.
44 |
45 | "Compile" the flowgraph for headless monitoring to the python-file:
46 | `user@system:~$ grcc -d . specmon-cli.grc`
47 |
48 | On your headless system run the software:
49 |
50 | `./specmon-cli.py -f 446.1e6 -s 2e6 -D 10 -g 30 -T 0.8`
51 | And you should see lines like this:
52 |
53 | `A,1.1,1576821964.22,U,2.8,1576821964.78`
54 |
55 | - A is *Above*,
56 | - 1.1 is the average low-value since the last measurement,
57 | - 1576821964.22 is the timestamp,
58 | - U is *Under* the threshold,
59 | - 2.8 is the maximum value reached during this trigger,
60 | - 1576821964.78 is the timestamp when dropped below the threshold.
61 |
62 |
63 | If you are happy with the result, start running it from cron and let it run for several days:
64 |
65 | ````
66 | crontab -l
67 | # m h dom mon dow command
68 | 0 * * * * /home/pi/bin/monit
69 | ````
70 | The script monit is provided in the source-tree. This runs the tool for an hour and creates a logfile per hour.
71 | Additionaly it creates a logfile with end-time of the script and (for a Raspberry Pi) the temperature. This option is default disabled.
72 |
73 | ### Postprocessing the data
74 | After running for 24 hours you can make a graph for the usage-statistics. Therefor you need to postprocess the data using "testspec":
75 |
76 | ````
77 | for i in `ls log/specmon2-200110*csv`; do ./testspec $i >> log/200110.log ; done
78 | ````
79 | And now plot the graphs:
80 | `./mkgraph 200110.log`
81 | This results in 3 graphs:
82 |
83 | + 200110.log-opening.png with the number of openings
84 | + 200110.log-percent.png with the percentage of time "open" or "used"
85 | + 200110.log-avgopen.png with the average time "open"
86 |
87 | View the graphs in your viewer.
88 | After the first week you can see patterns of usage over the week. After several weeks you start seeing patterns per day. First combine a week of data:
89 | `cat day1.log day2.log day3.log day4.log day5.log day6.log day7.log >> week.log`
90 | and plot a 3D graph for the week:
91 | `./weekgraph week.log`
92 | This creates a 3D plot over the entire week.
93 |
94 | ---
95 | ## Some suggestions for use
96 | ### Frequency suggestions
97 | **EU 70cm analog repeaters:**
98 |
99 | - Downlink: 430.000 - 430.400 MHz
100 | - Center-frequency: 430.200 MHz
101 | - Sample-rate: 2e6
102 | - Decimation: 5
103 |
104 | **EU 70cm DMR repeater:**
105 |
106 | - Downlink: 438.000 - 438.400 MHz
107 | - Center-frequency: 438.200 MHz
108 | - Sample-rate: 2e6
109 | - Decimation: 5
110 |
111 | **EU 2M analog repeaters:**
112 |
113 | - Downlink: 145.600 - 145.800 MHz
114 | - Center-frequency: 145.700 MHz
115 | - Sample-rate: 2e6
116 | - Decimation: 10
117 |
118 | **EU PMR446 [[4]]:**
119 |
120 | - Frequency span: 446.000 - 446.200 MHz
121 | - Center-frequency: 446.100 MHz
122 | - Sample-rate: 2e6
123 | - Decimation: 10
124 |
125 | Since the revision of june 2020 small bursts can trigger specmon and measured. AIS bursts are very short but can be measured. Settings are:
126 |
127 | **AIS bursts:**
128 |
129 | - Frequency span: 161.950 - 162.050 MHz
130 | - Center-frequency: 162.000 MHz
131 | - Sample-rate: 2e6
132 | - Decimation: 20
133 |
134 |
135 | ### Verbose mode
136 | Determining the threshold can also be achieved in headless mode. Run specmon_cli.py with the `-v 1` option.
137 | See `specmon_cli.py -h` for all the options.
138 |
139 | ### GNUradio 3.7 vs 3.8
140 | Although GNUradio 3.8 has been released for a while, i'm still using 3.7 branch. Why, would you ask. Pretty easy: Installing GNUradio on a raspberry pi for the headless mode is quite easy as it's in the repository. But it's the maintained 3.7 branch.
141 |
142 | ### Other SDR's
143 | You can select other SDR's to use. Currently specmon is build around the Osmocom-Source so every SDR supported in this block, can be used:
144 | `-d rtl=00000234` for RTL-dongle with serial 234
145 | `-d bladerf=0` for the first bladerf connected
146 | `-d hackrf=0` for the first hackrf connected
147 |
148 | For other SDR's the source-block in the Gnuradio Flowgraph needs to be exchanged.
149 |
150 | ## Help
151 |
152 | ````
153 | Usage: specmon_cli.py: [options]
154 |
155 | Options:
156 | -h, --help show this help message and exit
157 | -b BBGAIN, --bbgain=BBGAIN
158 | Set BB-Gain [default=30]
159 | -D DECIMATION, --decimation=DECIMATION
160 | Set Decimation [default=10]
161 | -d DEVICEID, --deviceid=DEVICEID
162 | Set Device ID [default=rtl=00000201]
163 | -f FREQ, --freq=FREQ Set Frequency [default=431.0M]
164 | -g RFGAIN, --rfgain=RFGAIN
165 | Set RF-Gain [default=30]
166 | -s SAMP_RATE, --samp-rate=SAMP_RATE
167 | Set Sample Rate [default=2.0M]
168 | -T THRESHOLD, --threshold=THRESHOLD
169 | Set Threshold [default=60.0]
170 | -v VERBOSE, --verbose=VERBOSE
171 | Set Verbose [default=0]
172 | -R RUNTIME, --runtime=RUNTIME
173 | Set Runtime in seconds [default=3590]
174 | ````
175 | Be aware that sample-rate and frequency must be in scientific notation. For example: `-s 2e6 -D 10 -f 446.1e6`.
176 |
177 | ## Revisions
178 | August 2020:
179 | Some minor updates on documentation and the script for running specmon from cron. Printing 2 decimals to increase resolution in testspec.
180 |
181 | June 2020:
182 | Software is capable of measuring shorter bursts.
183 | Reporting now has an average of the "low values", i.e. under the threshold, since the last trigger of the threshold.
184 | Reporting the max value measured during the trigger of the threshold.
185 |
186 | [RTL-SDR]: https://www.rtl-sdr.com/buy-rtl-sdr-dvb-t-dongles/
187 | [HackRF]: https://greatscottgadgets.com/hackrf/
188 | [PlutoSDR]: https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/adalm-pluto.html#eb-overview
189 | [BladeRF]: https://www.nuand.com/
190 | [4]: https://en.wikipedia.org/wiki/PMR446
191 | [5]: https://www.gnuradio.org/
192 | [gnuplot-palettes]: https://github.com/Gnuplotting/gnuplot-palettes
193 |
--------------------------------------------------------------------------------
/specmon2.grc:
--------------------------------------------------------------------------------
1 | options:
2 | parameters:
3 | author: PE1RIK
4 | category: '[GRC Hier Blocks]'
5 | cmake_opt: ''
6 | comment: ''
7 | copyright: ''
8 | description: ''
9 | gen_cmake: 'On'
10 | gen_linking: dynamic
11 | generate_options: no_gui
12 | hier_block_src_path: '.:'
13 | id: specmon2
14 | max_nouts: '0'
15 | output_language: python
16 | placement: (0,0)
17 | qt_qss_theme: ''
18 | realtime_scheduling: ''
19 | run: 'True'
20 | run_command: '{python} -u {filename}'
21 | run_options: run
22 | sizing_mode: fixed
23 | thread_safe_setters: ''
24 | title: ''
25 | window_size: ''
26 | states:
27 | bus_sink: false
28 | bus_source: false
29 | bus_structure: null
30 | coordinate: [8, 8]
31 | rotation: 0
32 | state: enabled
33 |
34 | blocks:
35 | - name: fhandler
36 | id: variable
37 | parameters:
38 | comment: ''
39 | value: '0'
40 | states:
41 | bus_sink: false
42 | bus_source: false
43 | bus_structure: null
44 | coordinate: [1232, 164.0]
45 | rotation: 0
46 | state: true
47 | - name: intcount
48 | id: variable
49 | parameters:
50 | comment: 'Integration count.
51 |
52 | Also used for normalisation
53 |
54 |
55 | vector_rate is vectors per second
56 |
57 |
58 | intcount = samp_rate/(fftsize * vector_rate)
59 |
60 |
61 | Bij vector_rate = 5 (200ms):
62 |
63 |
64 | intcount = samp_rate/(fftsize * 5)'
65 | value: int(samp_rate/(fftsize * 5))
66 | states:
67 | bus_sink: false
68 | bus_source: false
69 | bus_structure: null
70 | coordinate: [880, 316.0]
71 | rotation: 0
72 | state: enabled
73 | - name: start_state
74 | id: variable
75 | parameters:
76 | comment: ''
77 | value: '0'
78 | states:
79 | bus_sink: false
80 | bus_source: false
81 | bus_structure: null
82 | coordinate: [624, 368]
83 | rotation: 0
84 | state: enabled
85 | - name: bbgain
86 | id: parameter
87 | parameters:
88 | alias: ''
89 | comment: ''
90 | hide: none
91 | label: BB-Gain
92 | short_id: b
93 | type: intx
94 | value: '30'
95 | states:
96 | bus_sink: false
97 | bus_source: false
98 | bus_structure: null
99 | coordinate: [632, 32]
100 | rotation: 0
101 | state: enabled
102 | - name: blocks_add_xx_0
103 | id: blocks_add_xx
104 | parameters:
105 | affinity: ''
106 | alias: ''
107 | comment: ''
108 | maxoutbuf: '0'
109 | minoutbuf: '0'
110 | num_inputs: '2'
111 | type: float
112 | vlen: fftsize
113 | states:
114 | bus_sink: false
115 | bus_source: false
116 | bus_structure: null
117 | coordinate: [240, 536]
118 | rotation: 180
119 | state: enabled
120 | - name: blocks_complex_to_mag_squared_0
121 | id: blocks_complex_to_mag_squared
122 | parameters:
123 | affinity: ''
124 | alias: ''
125 | comment: ''
126 | maxoutbuf: '0'
127 | minoutbuf: '0'
128 | vlen: fftsize
129 | states:
130 | bus_sink: false
131 | bus_source: false
132 | bus_structure: null
133 | coordinate: [1080, 544]
134 | rotation: 180
135 | state: enabled
136 | - name: blocks_file_sink_0
137 | id: blocks_file_sink
138 | parameters:
139 | affinity: ''
140 | alias: ''
141 | append: 'False'
142 | comment: 'Debug option to save vector before
143 |
144 | calibration and specmon2 logics'
145 | file: '"/tmp/" + time.strftime("%y%m%d-%H%M") + "-" + str(int(freq)) + "-" + str(int(samp_rate))
146 | + "-" + str(fftsize) + ".pvector"'
147 | type: float
148 | unbuffered: 'False'
149 | vlen: fftsize
150 | states:
151 | bus_sink: false
152 | bus_source: false
153 | bus_structure: null
154 | coordinate: [184, 680]
155 | rotation: 180
156 | state: enabled
157 | - name: blocks_file_source_0
158 | id: blocks_file_source
159 | parameters:
160 | affinity: ''
161 | alias: ''
162 | begin_tag: pmt.PMT_NIL
163 | comment: ''
164 | file: calibvec
165 | length: '0'
166 | maxoutbuf: '0'
167 | minoutbuf: '0'
168 | offset: '0'
169 | repeat: 'True'
170 | type: float
171 | vlen: fftsize
172 | states:
173 | bus_sink: false
174 | bus_source: false
175 | bus_structure: null
176 | coordinate: [464, 696]
177 | rotation: 180
178 | state: enabled
179 | - name: blocks_head_0
180 | id: blocks_head
181 | parameters:
182 | affinity: ''
183 | alias: ''
184 | comment: ''
185 | maxoutbuf: '0'
186 | minoutbuf: '0'
187 | num_items: int(runtime*samp_rate)
188 | type: complex
189 | vlen: '1'
190 | states:
191 | bus_sink: false
192 | bus_source: false
193 | bus_structure: null
194 | coordinate: [320, 232.0]
195 | rotation: 0
196 | state: enabled
197 | - name: blocks_integrate_xx_0
198 | id: blocks_integrate_xx
199 | parameters:
200 | affinity: ''
201 | alias: ''
202 | comment: ''
203 | decim: intcount
204 | maxoutbuf: '0'
205 | minoutbuf: '0'
206 | type: float
207 | vlen: fftsize
208 | states:
209 | bus_sink: false
210 | bus_source: false
211 | bus_structure: null
212 | coordinate: [880, 536]
213 | rotation: 180
214 | state: enabled
215 | - name: blocks_moving_average_xx_0
216 | id: blocks_moving_average_xx
217 | parameters:
218 | affinity: ''
219 | alias: ''
220 | comment: ''
221 | length: '500'
222 | max_iter: '4000'
223 | maxoutbuf: '0'
224 | minoutbuf: '0'
225 | scale: 1.0/500
226 | type: complex
227 | vlen: '1'
228 | states:
229 | bus_sink: false
230 | bus_source: false
231 | bus_structure: null
232 | coordinate: [472, 288.0]
233 | rotation: 0
234 | state: enabled
235 | - name: blocks_multiply_const_vxx_0
236 | id: blocks_multiply_const_vxx
237 | parameters:
238 | affinity: ''
239 | alias: ''
240 | comment: Normalize integrated vectors
241 | const: '[1.0/intcount]*fftsize'
242 | maxoutbuf: '0'
243 | minoutbuf: '0'
244 | type: float
245 | vlen: fftsize
246 | states:
247 | bus_sink: false
248 | bus_source: false
249 | bus_structure: null
250 | coordinate: [648, 536]
251 | rotation: 180
252 | state: enabled
253 | - name: blocks_nlog10_ff_0
254 | id: blocks_nlog10_ff
255 | parameters:
256 | affinity: ''
257 | alias: ''
258 | comment: ''
259 | k: '0'
260 | maxoutbuf: '0'
261 | minoutbuf: '0'
262 | n: '10'
263 | vlen: fftsize
264 | states:
265 | bus_sink: false
266 | bus_source: false
267 | bus_structure: null
268 | coordinate: [456, 532]
269 | rotation: 180
270 | state: enabled
271 | - name: blocks_stream_to_vector_0
272 | id: blocks_stream_to_vector
273 | parameters:
274 | affinity: ''
275 | alias: ''
276 | comment: ''
277 | maxoutbuf: '0'
278 | minoutbuf: '0'
279 | num_items: fftsize
280 | type: complex
281 | vlen: '1'
282 | states:
283 | bus_sink: false
284 | bus_source: false
285 | bus_structure: null
286 | coordinate: [832, 248]
287 | rotation: 0
288 | state: enabled
289 | - name: blocks_sub_xx_0
290 | id: blocks_sub_xx
291 | parameters:
292 | affinity: ''
293 | alias: ''
294 | comment: ''
295 | maxoutbuf: '0'
296 | minoutbuf: '0'
297 | num_inputs: '2'
298 | type: complex
299 | vlen: '1'
300 | states:
301 | bus_sink: false
302 | bus_source: false
303 | bus_structure: null
304 | coordinate: [656, 224]
305 | rotation: 0
306 | state: enabled
307 | - name: calibvec
308 | id: parameter
309 | parameters:
310 | alias: ''
311 | comment: ''
312 | hide: none
313 | label: Calibration Vector
314 | short_id: c
315 | type: str
316 | value: '0'
317 | states:
318 | bus_sink: false
319 | bus_source: false
320 | bus_structure: null
321 | coordinate: [672, 656]
322 | rotation: 0
323 | state: enabled
324 | - name: deviceid
325 | id: parameter
326 | parameters:
327 | alias: ''
328 | comment: ''
329 | hide: none
330 | label: Device ID
331 | short_id: d
332 | type: str
333 | value: '"rtl=00000201"'
334 | states:
335 | bus_sink: false
336 | bus_source: false
337 | bus_structure: null
338 | coordinate: [240, 32]
339 | rotation: 0
340 | state: enabled
341 | - name: fft_vxx_0
342 | id: fft_vxx
343 | parameters:
344 | affinity: ''
345 | alias: ''
346 | comment: ''
347 | fft_size: fftsize
348 | forward: 'True'
349 | maxoutbuf: '0'
350 | minoutbuf: '0'
351 | nthreads: '1'
352 | shift: 'True'
353 | type: complex
354 | window: window.blackmanharris(fftsize)
355 | states:
356 | bus_sink: false
357 | bus_source: false
358 | bus_structure: null
359 | coordinate: [1024, 216]
360 | rotation: 0
361 | state: enabled
362 | - name: fftsize
363 | id: parameter
364 | parameters:
365 | alias: ''
366 | comment: ''
367 | hide: none
368 | label: FFT size
369 | short_id: F
370 | type: intx
371 | value: '1024'
372 | states:
373 | bus_sink: false
374 | bus_source: false
375 | bus_structure: null
376 | coordinate: [856, 652]
377 | rotation: 0
378 | state: enabled
379 | - name: freq
380 | id: parameter
381 | parameters:
382 | alias: ''
383 | comment: ''
384 | hide: none
385 | label: Frequency
386 | short_id: f
387 | type: eng_float
388 | value: 145e6
389 | states:
390 | bus_sink: false
391 | bus_source: false
392 | bus_structure: null
393 | coordinate: [392, 32]
394 | rotation: 0
395 | state: enabled
396 | - name: import_0
397 | id: import
398 | parameters:
399 | alias: ''
400 | comment: "Required when not \nusing osmocom source"
401 | imports: import time
402 | states:
403 | bus_sink: false
404 | bus_source: false
405 | bus_structure: null
406 | coordinate: [16, 680]
407 | rotation: 0
408 | state: enabled
409 | - name: osmosdr_source_0
410 | id: osmosdr_source
411 | parameters:
412 | affinity: ''
413 | alias: ''
414 | ant0: ''
415 | ant1: ''
416 | ant10: ''
417 | ant11: ''
418 | ant12: ''
419 | ant13: ''
420 | ant14: ''
421 | ant15: ''
422 | ant16: ''
423 | ant17: ''
424 | ant18: ''
425 | ant19: ''
426 | ant2: ''
427 | ant20: ''
428 | ant21: ''
429 | ant22: ''
430 | ant23: ''
431 | ant24: ''
432 | ant25: ''
433 | ant26: ''
434 | ant27: ''
435 | ant28: ''
436 | ant29: ''
437 | ant3: ''
438 | ant30: ''
439 | ant31: ''
440 | ant4: ''
441 | ant5: ''
442 | ant6: ''
443 | ant7: ''
444 | ant8: ''
445 | ant9: ''
446 | args: deviceid
447 | bb_gain0: bbgain
448 | bb_gain1: '20'
449 | bb_gain10: '20'
450 | bb_gain11: '20'
451 | bb_gain12: '20'
452 | bb_gain13: '20'
453 | bb_gain14: '20'
454 | bb_gain15: '20'
455 | bb_gain16: '20'
456 | bb_gain17: '20'
457 | bb_gain18: '20'
458 | bb_gain19: '20'
459 | bb_gain2: '20'
460 | bb_gain20: '20'
461 | bb_gain21: '20'
462 | bb_gain22: '20'
463 | bb_gain23: '20'
464 | bb_gain24: '20'
465 | bb_gain25: '20'
466 | bb_gain26: '20'
467 | bb_gain27: '20'
468 | bb_gain28: '20'
469 | bb_gain29: '20'
470 | bb_gain3: '20'
471 | bb_gain30: '20'
472 | bb_gain31: '20'
473 | bb_gain4: '20'
474 | bb_gain5: '20'
475 | bb_gain6: '20'
476 | bb_gain7: '20'
477 | bb_gain8: '20'
478 | bb_gain9: '20'
479 | bw0: '0'
480 | bw1: '0'
481 | bw10: '0'
482 | bw11: '0'
483 | bw12: '0'
484 | bw13: '0'
485 | bw14: '0'
486 | bw15: '0'
487 | bw16: '0'
488 | bw17: '0'
489 | bw18: '0'
490 | bw19: '0'
491 | bw2: '0'
492 | bw20: '0'
493 | bw21: '0'
494 | bw22: '0'
495 | bw23: '0'
496 | bw24: '0'
497 | bw25: '0'
498 | bw26: '0'
499 | bw27: '0'
500 | bw28: '0'
501 | bw29: '0'
502 | bw3: '0'
503 | bw30: '0'
504 | bw31: '0'
505 | bw4: '0'
506 | bw5: '0'
507 | bw6: '0'
508 | bw7: '0'
509 | bw8: '0'
510 | bw9: '0'
511 | clock_source0: ''
512 | clock_source1: ''
513 | clock_source2: ''
514 | clock_source3: ''
515 | clock_source4: ''
516 | clock_source5: ''
517 | clock_source6: ''
518 | clock_source7: ''
519 | comment: ''
520 | corr0: '0'
521 | corr1: '0'
522 | corr10: '0'
523 | corr11: '0'
524 | corr12: '0'
525 | corr13: '0'
526 | corr14: '0'
527 | corr15: '0'
528 | corr16: '0'
529 | corr17: '0'
530 | corr18: '0'
531 | corr19: '0'
532 | corr2: '0'
533 | corr20: '0'
534 | corr21: '0'
535 | corr22: '0'
536 | corr23: '0'
537 | corr24: '0'
538 | corr25: '0'
539 | corr26: '0'
540 | corr27: '0'
541 | corr28: '0'
542 | corr29: '0'
543 | corr3: '0'
544 | corr30: '0'
545 | corr31: '0'
546 | corr4: '0'
547 | corr5: '0'
548 | corr6: '0'
549 | corr7: '0'
550 | corr8: '0'
551 | corr9: '0'
552 | dc_offset_mode0: '0'
553 | dc_offset_mode1: '0'
554 | dc_offset_mode10: '0'
555 | dc_offset_mode11: '0'
556 | dc_offset_mode12: '0'
557 | dc_offset_mode13: '0'
558 | dc_offset_mode14: '0'
559 | dc_offset_mode15: '0'
560 | dc_offset_mode16: '0'
561 | dc_offset_mode17: '0'
562 | dc_offset_mode18: '0'
563 | dc_offset_mode19: '0'
564 | dc_offset_mode2: '0'
565 | dc_offset_mode20: '0'
566 | dc_offset_mode21: '0'
567 | dc_offset_mode22: '0'
568 | dc_offset_mode23: '0'
569 | dc_offset_mode24: '0'
570 | dc_offset_mode25: '0'
571 | dc_offset_mode26: '0'
572 | dc_offset_mode27: '0'
573 | dc_offset_mode28: '0'
574 | dc_offset_mode29: '0'
575 | dc_offset_mode3: '0'
576 | dc_offset_mode30: '0'
577 | dc_offset_mode31: '0'
578 | dc_offset_mode4: '0'
579 | dc_offset_mode5: '0'
580 | dc_offset_mode6: '0'
581 | dc_offset_mode7: '0'
582 | dc_offset_mode8: '0'
583 | dc_offset_mode9: '0'
584 | freq0: freq
585 | freq1: 100e6
586 | freq10: 100e6
587 | freq11: 100e6
588 | freq12: 100e6
589 | freq13: 100e6
590 | freq14: 100e6
591 | freq15: 100e6
592 | freq16: 100e6
593 | freq17: 100e6
594 | freq18: 100e6
595 | freq19: 100e6
596 | freq2: 100e6
597 | freq20: 100e6
598 | freq21: 100e6
599 | freq22: 100e6
600 | freq23: 100e6
601 | freq24: 100e6
602 | freq25: 100e6
603 | freq26: 100e6
604 | freq27: 100e6
605 | freq28: 100e6
606 | freq29: 100e6
607 | freq3: 100e6
608 | freq30: 100e6
609 | freq31: 100e6
610 | freq4: 100e6
611 | freq5: 100e6
612 | freq6: 100e6
613 | freq7: 100e6
614 | freq8: 100e6
615 | freq9: 100e6
616 | gain0: rfgain
617 | gain1: '10'
618 | gain10: '10'
619 | gain11: '10'
620 | gain12: '10'
621 | gain13: '10'
622 | gain14: '10'
623 | gain15: '10'
624 | gain16: '10'
625 | gain17: '10'
626 | gain18: '10'
627 | gain19: '10'
628 | gain2: '10'
629 | gain20: '10'
630 | gain21: '10'
631 | gain22: '10'
632 | gain23: '10'
633 | gain24: '10'
634 | gain25: '10'
635 | gain26: '10'
636 | gain27: '10'
637 | gain28: '10'
638 | gain29: '10'
639 | gain3: '10'
640 | gain30: '10'
641 | gain31: '10'
642 | gain4: '10'
643 | gain5: '10'
644 | gain6: '10'
645 | gain7: '10'
646 | gain8: '10'
647 | gain9: '10'
648 | gain_mode0: 'False'
649 | gain_mode1: 'False'
650 | gain_mode10: 'False'
651 | gain_mode11: 'False'
652 | gain_mode12: 'False'
653 | gain_mode13: 'False'
654 | gain_mode14: 'False'
655 | gain_mode15: 'False'
656 | gain_mode16: 'False'
657 | gain_mode17: 'False'
658 | gain_mode18: 'False'
659 | gain_mode19: 'False'
660 | gain_mode2: 'False'
661 | gain_mode20: 'False'
662 | gain_mode21: 'False'
663 | gain_mode22: 'False'
664 | gain_mode23: 'False'
665 | gain_mode24: 'False'
666 | gain_mode25: 'False'
667 | gain_mode26: 'False'
668 | gain_mode27: 'False'
669 | gain_mode28: 'False'
670 | gain_mode29: 'False'
671 | gain_mode3: 'False'
672 | gain_mode30: 'False'
673 | gain_mode31: 'False'
674 | gain_mode4: 'False'
675 | gain_mode5: 'False'
676 | gain_mode6: 'False'
677 | gain_mode7: 'False'
678 | gain_mode8: 'False'
679 | gain_mode9: 'False'
680 | if_gain0: '20'
681 | if_gain1: '20'
682 | if_gain10: '20'
683 | if_gain11: '20'
684 | if_gain12: '20'
685 | if_gain13: '20'
686 | if_gain14: '20'
687 | if_gain15: '20'
688 | if_gain16: '20'
689 | if_gain17: '20'
690 | if_gain18: '20'
691 | if_gain19: '20'
692 | if_gain2: '20'
693 | if_gain20: '20'
694 | if_gain21: '20'
695 | if_gain22: '20'
696 | if_gain23: '20'
697 | if_gain24: '20'
698 | if_gain25: '20'
699 | if_gain26: '20'
700 | if_gain27: '20'
701 | if_gain28: '20'
702 | if_gain29: '20'
703 | if_gain3: '20'
704 | if_gain30: '20'
705 | if_gain31: '20'
706 | if_gain4: '20'
707 | if_gain5: '20'
708 | if_gain6: '20'
709 | if_gain7: '20'
710 | if_gain8: '20'
711 | if_gain9: '20'
712 | iq_balance_mode0: '0'
713 | iq_balance_mode1: '0'
714 | iq_balance_mode10: '0'
715 | iq_balance_mode11: '0'
716 | iq_balance_mode12: '0'
717 | iq_balance_mode13: '0'
718 | iq_balance_mode14: '0'
719 | iq_balance_mode15: '0'
720 | iq_balance_mode16: '0'
721 | iq_balance_mode17: '0'
722 | iq_balance_mode18: '0'
723 | iq_balance_mode19: '0'
724 | iq_balance_mode2: '0'
725 | iq_balance_mode20: '0'
726 | iq_balance_mode21: '0'
727 | iq_balance_mode22: '0'
728 | iq_balance_mode23: '0'
729 | iq_balance_mode24: '0'
730 | iq_balance_mode25: '0'
731 | iq_balance_mode26: '0'
732 | iq_balance_mode27: '0'
733 | iq_balance_mode28: '0'
734 | iq_balance_mode29: '0'
735 | iq_balance_mode3: '0'
736 | iq_balance_mode30: '0'
737 | iq_balance_mode31: '0'
738 | iq_balance_mode4: '0'
739 | iq_balance_mode5: '0'
740 | iq_balance_mode6: '0'
741 | iq_balance_mode7: '0'
742 | iq_balance_mode8: '0'
743 | iq_balance_mode9: '0'
744 | maxoutbuf: '0'
745 | minoutbuf: '0'
746 | nchan: '1'
747 | num_mboards: '1'
748 | sample_rate: samp_rate
749 | sync: sync
750 | time_source0: ''
751 | time_source1: ''
752 | time_source2: ''
753 | time_source3: ''
754 | time_source4: ''
755 | time_source5: ''
756 | time_source6: ''
757 | time_source7: ''
758 | type: fc32
759 | states:
760 | bus_sink: false
761 | bus_source: false
762 | bus_structure: null
763 | coordinate: [0, 236.0]
764 | rotation: 0
765 | state: enabled
766 | - name: outfile
767 | id: parameter
768 | parameters:
769 | alias: ''
770 | comment: ''
771 | hide: none
772 | label: Output File
773 | short_id: O
774 | type: str
775 | value: '"/tmp/logfile.csv"'
776 | states:
777 | bus_sink: false
778 | bus_source: false
779 | bus_structure: null
780 | coordinate: [1192, 36.0]
781 | rotation: 0
782 | state: true
783 | - name: rfgain
784 | id: parameter
785 | parameters:
786 | alias: ''
787 | comment: ''
788 | hide: none
789 | label: RF-Gain
790 | short_id: g
791 | type: intx
792 | value: '40'
793 | states:
794 | bus_sink: false
795 | bus_source: false
796 | bus_structure: null
797 | coordinate: [520, 32]
798 | rotation: 0
799 | state: enabled
800 | - name: runtime
801 | id: parameter
802 | parameters:
803 | alias: ''
804 | comment: ''
805 | hide: none
806 | label: ''
807 | short_id: R
808 | type: intx
809 | value: '3590'
810 | states:
811 | bus_sink: false
812 | bus_source: false
813 | bus_structure: null
814 | coordinate: [320, 328.0]
815 | rotation: 0
816 | state: enabled
817 | - name: samp_rate
818 | id: parameter
819 | parameters:
820 | alias: ''
821 | comment: ''
822 | hide: none
823 | label: Sample Rate
824 | short_id: s
825 | type: eng_float
826 | value: 2e6
827 | states:
828 | bus_sink: false
829 | bus_source: false
830 | bus_structure: null
831 | coordinate: [872, 32]
832 | rotation: 0
833 | state: enabled
834 | - name: specmon_block
835 | id: epy_block
836 | parameters:
837 | _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\
838 | \ GRC will instantiate the first class it finds\nto get ports and parameters\
839 | \ of your block. The arguments to __init__ will\nbe the parameters. All of\
840 | \ them are required to have default values!\n\"\"\"\n\n#from __future__ import\
841 | \ print_function\nimport numpy as np\nfrom gnuradio import gr\nimport time\n\
842 | \n\nclass blk(gr.sync_block): # other base classes are basic_block, decim_block,\
843 | \ interp_block\n \"\"\"Specmon data analysis block. \n This block is the\
844 | \ improved version for specmon\n \"\"\"\n\n\t# Don't use \"logfile\" as varname\
845 | \ as it's reserved in GRC\n def __init__(self, fftsize=1024, start_state=0,\
846 | \ threshold=1.0, verbose=0, reportfile=\"/tmp/logfile.csv\"): # only default\
847 | \ arguments here\n \"\"\"arguments to this function show up as parameters\
848 | \ in GRC\"\"\"\n self.fftsize = fftsize\n self.start_state = start_state\n\
849 | \ self.threshold = threshold\n self.verbose = verbose\n \
850 | \ self.maxval = 0\n self.sumval = 0\n self.lowcounter = 1\n \
851 | \ self.reportfile = reportfile\n gr.sync_block.__init__(\n \
852 | \ self,\n name='Specmon2', # will show up in GRC\n \
853 | \ in_sig=[(np.float32,self.fftsize)],\n out_sig=None\n \
854 | \ )\n # Print startline\n self.outfile = open(reportfile, \"\
855 | a\")\n print (\"S,%.2f,H,%s,T,%.2f\" % ( time.time(), str(time.strftime(\"\
856 | %H\")), threshold ), file=self.outfile, flush=True )\n \n def work(self,\
857 | \ input_items, output_items):\n \n for j in (range(len(input_items[0]))):\n\
858 | \ if len(input_items[0][j]) == self.fftsize:\n speclist\
859 | \ = np.array(input_items[0][0])\n # Peak for max-value\n \
860 | \ curval = np.amax(speclist)\n # Median for median\
861 | \ noise level\n noiseval = np.median(speclist)\n \
862 | \ if self.verbose == 1:\n #print (\"%.2f\" % curval)\n\
863 | \ print (\"Current value: %.2f M %1.2f N %i S %.3f\" % (\
864 | \ curval, self.maxval, self.lowcounter, self.sumval ) )\n \
865 | \ \n if curval > self.maxval:\n self.maxval\
866 | \ = curval\n \n if curval > self.threshold and\
867 | \ self.start_state == 0:\n # Signal triggers the threshold\n\
868 | \ self.start_state = 1\n lowavg = self.sumval\
869 | \ / self.lowcounter\n #print (\"A,%.2f,%.2f,\" % ( curval,\
870 | \ time.time() ), end=\"\" )\n print (\"A,%.2f,%.2f,\" % (\
871 | \ lowavg, time.time() ), end=\"\", file=self.outfile )\n elif\
872 | \ curval < self.threshold and self.start_state == 1:\n #\
873 | \ Signal drops below threshold\n #print (\"U,%.2f,%.2f\"\
874 | \ % ( curval, time.time() ), end=\"\\n\")\n print (\"U,%.2f,%.2f\"\
875 | \ % ( self.maxval, time.time() ), end=\"\\n\", file=self.outfile, flush=True)\n\
876 | \ self.start_state = 0\n self.sumval =\
877 | \ 0\n self.lowcounter = 1\n self.maxval\
878 | \ = 0 \n else:\n # Signal remains\
879 | \ under threshold\n #self.sumval += curval\n \
880 | \ self.sumval += noiseval\n self.lowcounter += 1\n\
881 | \t\t\t\n \n return len(input_items[0])\n"
882 | affinity: ''
883 | alias: ''
884 | comment: ''
885 | fftsize: fftsize
886 | maxoutbuf: '0'
887 | minoutbuf: '0'
888 | reportfile: outfile
889 | start_state: start_state
890 | threshold: threshold
891 | verbose: verbose
892 | states:
893 | _io_cache: ('Specmon2', 'blk', [('fftsize', '1024'), ('start_state', '0'), ('threshold',
894 | '1.0'), ('verbose', '0'), ('reportfile', "'/tmp/logfile.csv'")], [('0', 'float',
895 | 1024)], [], 'Specmon data analysis block. \n This block is the improved version
896 | for specmon\n ', ['fftsize', 'reportfile', 'start_state', 'threshold', 'verbose'])
897 | bus_sink: false
898 | bus_source: false
899 | bus_structure: null
900 | coordinate: [16, 516.0]
901 | rotation: 180
902 | state: enabled
903 | - name: threshold
904 | id: parameter
905 | parameters:
906 | alias: ''
907 | comment: ''
908 | hide: none
909 | label: Threshold
910 | short_id: T
911 | type: eng_float
912 | value: '.1'
913 | states:
914 | bus_sink: false
915 | bus_source: false
916 | bus_structure: null
917 | coordinate: [752, 32]
918 | rotation: 0
919 | state: enabled
920 | - name: verbose
921 | id: parameter
922 | parameters:
923 | alias: ''
924 | comment: ''
925 | hide: none
926 | label: Print verbose values
927 | short_id: v
928 | type: intx
929 | value: '0'
930 | states:
931 | bus_sink: false
932 | bus_source: false
933 | bus_structure: null
934 | coordinate: [1016, 32]
935 | rotation: 0
936 | state: enabled
937 |
938 | connections:
939 | - [blocks_add_xx_0, '0', specmon_block, '0']
940 | - [blocks_complex_to_mag_squared_0, '0', blocks_integrate_xx_0, '0']
941 | - [blocks_file_source_0, '0', blocks_add_xx_0, '1']
942 | - [blocks_head_0, '0', blocks_moving_average_xx_0, '0']
943 | - [blocks_head_0, '0', blocks_sub_xx_0, '0']
944 | - [blocks_integrate_xx_0, '0', blocks_multiply_const_vxx_0, '0']
945 | - [blocks_moving_average_xx_0, '0', blocks_sub_xx_0, '1']
946 | - [blocks_multiply_const_vxx_0, '0', blocks_nlog10_ff_0, '0']
947 | - [blocks_nlog10_ff_0, '0', blocks_add_xx_0, '0']
948 | - [blocks_nlog10_ff_0, '0', blocks_file_sink_0, '0']
949 | - [blocks_stream_to_vector_0, '0', fft_vxx_0, '0']
950 | - [blocks_sub_xx_0, '0', blocks_stream_to_vector_0, '0']
951 | - [fft_vxx_0, '0', blocks_complex_to_mag_squared_0, '0']
952 | - [osmosdr_source_0, '0', blocks_head_0, '0']
953 |
954 | metadata:
955 | file_format: 1
956 |
--------------------------------------------------------------------------------
/specmon2_gui.grc:
--------------------------------------------------------------------------------
1 | options:
2 | parameters:
3 | author: PE1RIK
4 | category: '[GRC Hier Blocks]'
5 | cmake_opt: ''
6 | comment: ''
7 | copyright: ''
8 | description: ''
9 | gen_cmake: 'On'
10 | gen_linking: dynamic
11 | generate_options: qt_gui
12 | hier_block_src_path: '.:'
13 | id: specmon2_gui
14 | max_nouts: '0'
15 | output_language: python
16 | placement: (0,0)
17 | qt_qss_theme: ''
18 | realtime_scheduling: ''
19 | run: 'True'
20 | run_command: '{python} -u {filename}'
21 | run_options: run
22 | sizing_mode: fixed
23 | thread_safe_setters: ''
24 | title: ''
25 | window_size: ''
26 | states:
27 | bus_sink: false
28 | bus_source: false
29 | bus_structure: null
30 | coordinate: [8, 8]
31 | rotation: 0
32 | state: enabled
33 |
34 | blocks:
35 | - name: freq
36 | id: variable_qtgui_range
37 | parameters:
38 | comment: ''
39 | gui_hint: ''
40 | label: ''
41 | min_len: '200'
42 | orient: Qt.Horizontal
43 | rangeType: float
44 | start: 70e6
45 | step: 25e3
46 | stop: 1e9
47 | value: 145e6
48 | widget: counter_slider
49 | states:
50 | bus_sink: false
51 | bus_source: false
52 | bus_structure: null
53 | coordinate: [328, 32]
54 | rotation: 0
55 | state: enabled
56 | - name: intcount
57 | id: variable
58 | parameters:
59 | comment: 'Integration count.
60 |
61 | Also used for normalisation'
62 | value: int(samp_rate/(fftsize * 5))
63 | states:
64 | bus_sink: false
65 | bus_source: false
66 | bus_structure: null
67 | coordinate: [1120, 632]
68 | rotation: 0
69 | state: enabled
70 | - name: rfgain
71 | id: variable_qtgui_range
72 | parameters:
73 | comment: ''
74 | gui_hint: ''
75 | label: ''
76 | min_len: '200'
77 | orient: Qt.Horizontal
78 | rangeType: float
79 | start: '0'
80 | step: '1'
81 | stop: '70'
82 | value: '20'
83 | widget: counter_slider
84 | states:
85 | bus_sink: false
86 | bus_source: false
87 | bus_structure: null
88 | coordinate: [496, 32]
89 | rotation: 0
90 | state: enabled
91 | - name: start_state
92 | id: variable
93 | parameters:
94 | comment: ''
95 | value: '0'
96 | states:
97 | bus_sink: false
98 | bus_source: false
99 | bus_structure: null
100 | coordinate: [880, 632]
101 | rotation: 0
102 | state: enabled
103 | - name: threshold
104 | id: variable_qtgui_range
105 | parameters:
106 | comment: ''
107 | gui_hint: ''
108 | label: ''
109 | min_len: '200'
110 | orient: Qt.Horizontal
111 | rangeType: float
112 | start: '0'
113 | step: '.1'
114 | stop: '50'
115 | value: '10'
116 | widget: counter_slider
117 | states:
118 | bus_sink: false
119 | bus_source: false
120 | bus_structure: null
121 | coordinate: [672, 348.0]
122 | rotation: 0
123 | state: enabled
124 | - name: bbgain
125 | id: parameter
126 | parameters:
127 | alias: ''
128 | comment: ''
129 | hide: none
130 | label: BB-Gain
131 | short_id: b
132 | type: intx
133 | value: '30'
134 | states:
135 | bus_sink: false
136 | bus_source: false
137 | bus_structure: null
138 | coordinate: [632, 32]
139 | rotation: 0
140 | state: enabled
141 | - name: blocks_add_xx_0
142 | id: blocks_add_xx
143 | parameters:
144 | affinity: ''
145 | alias: ''
146 | comment: ''
147 | maxoutbuf: '0'
148 | minoutbuf: '0'
149 | num_inputs: '2'
150 | type: float
151 | vlen: fftsize
152 | states:
153 | bus_sink: false
154 | bus_source: false
155 | bus_structure: null
156 | coordinate: [296, 496]
157 | rotation: 180
158 | state: enabled
159 | - name: blocks_complex_to_mag_squared_0
160 | id: blocks_complex_to_mag_squared
161 | parameters:
162 | affinity: ''
163 | alias: ''
164 | comment: ''
165 | maxoutbuf: '0'
166 | minoutbuf: '0'
167 | vlen: fftsize
168 | states:
169 | bus_sink: false
170 | bus_source: false
171 | bus_structure: null
172 | coordinate: [1088, 504]
173 | rotation: 180
174 | state: enabled
175 | - name: blocks_file_source_0
176 | id: blocks_file_source
177 | parameters:
178 | affinity: ''
179 | alias: ''
180 | begin_tag: pmt.PMT_NIL
181 | comment: ''
182 | file: calibvec
183 | length: '0'
184 | maxoutbuf: '0'
185 | minoutbuf: '0'
186 | offset: '0'
187 | repeat: 'True'
188 | type: float
189 | vlen: fftsize
190 | states:
191 | bus_sink: false
192 | bus_source: false
193 | bus_structure: null
194 | coordinate: [496, 656]
195 | rotation: 180
196 | state: enabled
197 | - name: blocks_head_0
198 | id: blocks_head
199 | parameters:
200 | affinity: ''
201 | alias: ''
202 | comment: ''
203 | maxoutbuf: '0'
204 | minoutbuf: '0'
205 | num_items: int(runtime*samp_rate)
206 | type: complex
207 | vlen: '1'
208 | states:
209 | bus_sink: false
210 | bus_source: false
211 | bus_structure: null
212 | coordinate: [272, 232]
213 | rotation: 0
214 | state: enabled
215 | - name: blocks_integrate_xx_0
216 | id: blocks_integrate_xx
217 | parameters:
218 | affinity: ''
219 | alias: ''
220 | comment: ''
221 | decim: intcount
222 | maxoutbuf: '0'
223 | minoutbuf: '0'
224 | type: float
225 | vlen: fftsize
226 | states:
227 | bus_sink: false
228 | bus_source: false
229 | bus_structure: null
230 | coordinate: [896, 496]
231 | rotation: 180
232 | state: enabled
233 | - name: blocks_moving_average_xx_0
234 | id: blocks_moving_average_xx
235 | parameters:
236 | affinity: ''
237 | alias: ''
238 | comment: ''
239 | length: '500'
240 | max_iter: '4000'
241 | maxoutbuf: '0'
242 | minoutbuf: '0'
243 | scale: 1.0/500
244 | type: complex
245 | vlen: '1'
246 | states:
247 | bus_sink: false
248 | bus_source: false
249 | bus_structure: null
250 | coordinate: [480, 280]
251 | rotation: 0
252 | state: enabled
253 | - name: blocks_multiply_const_vxx_0
254 | id: blocks_multiply_const_vxx
255 | parameters:
256 | affinity: ''
257 | alias: ''
258 | comment: Normalize integrated vectors
259 | const: '[1.0/intcount]*fftsize'
260 | maxoutbuf: '0'
261 | minoutbuf: '0'
262 | type: float
263 | vlen: fftsize
264 | states:
265 | bus_sink: false
266 | bus_source: false
267 | bus_structure: null
268 | coordinate: [664, 496]
269 | rotation: 180
270 | state: enabled
271 | - name: blocks_nlog10_ff_0
272 | id: blocks_nlog10_ff
273 | parameters:
274 | affinity: ''
275 | alias: ''
276 | comment: ''
277 | k: '0'
278 | maxoutbuf: '0'
279 | minoutbuf: '0'
280 | n: '10'
281 | vlen: fftsize
282 | states:
283 | bus_sink: false
284 | bus_source: false
285 | bus_structure: null
286 | coordinate: [488, 488]
287 | rotation: 180
288 | state: enabled
289 | - name: blocks_stream_to_vector_0
290 | id: blocks_stream_to_vector
291 | parameters:
292 | affinity: ''
293 | alias: ''
294 | comment: ''
295 | maxoutbuf: '0'
296 | minoutbuf: '0'
297 | num_items: fftsize
298 | type: complex
299 | vlen: '1'
300 | states:
301 | bus_sink: false
302 | bus_source: false
303 | bus_structure: null
304 | coordinate: [848, 248]
305 | rotation: 0
306 | state: enabled
307 | - name: blocks_sub_xx_0
308 | id: blocks_sub_xx
309 | parameters:
310 | affinity: ''
311 | alias: ''
312 | comment: ''
313 | maxoutbuf: '0'
314 | minoutbuf: '0'
315 | num_inputs: '2'
316 | type: complex
317 | vlen: '1'
318 | states:
319 | bus_sink: false
320 | bus_source: false
321 | bus_structure: null
322 | coordinate: [680, 224]
323 | rotation: 0
324 | state: enabled
325 | - name: blocks_vector_source_x_0
326 | id: blocks_vector_source_x
327 | parameters:
328 | affinity: ''
329 | alias: ''
330 | comment: ''
331 | maxoutbuf: '0'
332 | minoutbuf: '0'
333 | repeat: 'True'
334 | tags: '[]'
335 | type: float
336 | vector: '[threshold]*fftsize'
337 | vlen: fftsize
338 | states:
339 | bus_sink: false
340 | bus_source: false
341 | bus_structure: null
342 | coordinate: [296, 648]
343 | rotation: 180
344 | state: enabled
345 | - name: calibvec
346 | id: parameter
347 | parameters:
348 | alias: ''
349 | comment: ''
350 | hide: none
351 | label: Calibration Vector
352 | short_id: c
353 | type: str
354 | value: /home/bart/grc/210926-zero-2048.vec
355 | states:
356 | bus_sink: false
357 | bus_source: false
358 | bus_structure: null
359 | coordinate: [664, 640]
360 | rotation: 0
361 | state: enabled
362 | - name: deviceid
363 | id: parameter
364 | parameters:
365 | alias: ''
366 | comment: ''
367 | hide: none
368 | label: Device ID
369 | short_id: d
370 | type: str
371 | value: rtl=0
372 | states:
373 | bus_sink: false
374 | bus_source: false
375 | bus_structure: null
376 | coordinate: [200, 32.0]
377 | rotation: 0
378 | state: enabled
379 | - name: fft_vxx_0
380 | id: fft_vxx
381 | parameters:
382 | affinity: ''
383 | alias: ''
384 | comment: ''
385 | fft_size: fftsize
386 | forward: 'True'
387 | maxoutbuf: '0'
388 | minoutbuf: '0'
389 | nthreads: '1'
390 | shift: 'True'
391 | type: complex
392 | window: window.blackmanharris(fftsize)
393 | states:
394 | bus_sink: false
395 | bus_source: false
396 | bus_structure: null
397 | coordinate: [1056, 216]
398 | rotation: 0
399 | state: enabled
400 | - name: fftsize
401 | id: parameter
402 | parameters:
403 | alias: ''
404 | comment: ''
405 | hide: none
406 | label: FFT size
407 | short_id: F
408 | type: intx
409 | value: '1024'
410 | states:
411 | bus_sink: false
412 | bus_source: false
413 | bus_structure: null
414 | coordinate: [880, 736]
415 | rotation: 0
416 | state: enabled
417 | - name: osmosdr_source_0
418 | id: osmosdr_source
419 | parameters:
420 | affinity: ''
421 | alias: ''
422 | ant0: ''
423 | ant1: ''
424 | ant10: ''
425 | ant11: ''
426 | ant12: ''
427 | ant13: ''
428 | ant14: ''
429 | ant15: ''
430 | ant16: ''
431 | ant17: ''
432 | ant18: ''
433 | ant19: ''
434 | ant2: ''
435 | ant20: ''
436 | ant21: ''
437 | ant22: ''
438 | ant23: ''
439 | ant24: ''
440 | ant25: ''
441 | ant26: ''
442 | ant27: ''
443 | ant28: ''
444 | ant29: ''
445 | ant3: ''
446 | ant30: ''
447 | ant31: ''
448 | ant4: ''
449 | ant5: ''
450 | ant6: ''
451 | ant7: ''
452 | ant8: ''
453 | ant9: ''
454 | args: deviceid
455 | bb_gain0: bbgain
456 | bb_gain1: '20'
457 | bb_gain10: '20'
458 | bb_gain11: '20'
459 | bb_gain12: '20'
460 | bb_gain13: '20'
461 | bb_gain14: '20'
462 | bb_gain15: '20'
463 | bb_gain16: '20'
464 | bb_gain17: '20'
465 | bb_gain18: '20'
466 | bb_gain19: '20'
467 | bb_gain2: '20'
468 | bb_gain20: '20'
469 | bb_gain21: '20'
470 | bb_gain22: '20'
471 | bb_gain23: '20'
472 | bb_gain24: '20'
473 | bb_gain25: '20'
474 | bb_gain26: '20'
475 | bb_gain27: '20'
476 | bb_gain28: '20'
477 | bb_gain29: '20'
478 | bb_gain3: '20'
479 | bb_gain30: '20'
480 | bb_gain31: '20'
481 | bb_gain4: '20'
482 | bb_gain5: '20'
483 | bb_gain6: '20'
484 | bb_gain7: '20'
485 | bb_gain8: '20'
486 | bb_gain9: '20'
487 | bw0: '0'
488 | bw1: '0'
489 | bw10: '0'
490 | bw11: '0'
491 | bw12: '0'
492 | bw13: '0'
493 | bw14: '0'
494 | bw15: '0'
495 | bw16: '0'
496 | bw17: '0'
497 | bw18: '0'
498 | bw19: '0'
499 | bw2: '0'
500 | bw20: '0'
501 | bw21: '0'
502 | bw22: '0'
503 | bw23: '0'
504 | bw24: '0'
505 | bw25: '0'
506 | bw26: '0'
507 | bw27: '0'
508 | bw28: '0'
509 | bw29: '0'
510 | bw3: '0'
511 | bw30: '0'
512 | bw31: '0'
513 | bw4: '0'
514 | bw5: '0'
515 | bw6: '0'
516 | bw7: '0'
517 | bw8: '0'
518 | bw9: '0'
519 | clock_source0: ''
520 | clock_source1: ''
521 | clock_source2: ''
522 | clock_source3: ''
523 | clock_source4: ''
524 | clock_source5: ''
525 | clock_source6: ''
526 | clock_source7: ''
527 | comment: ''
528 | corr0: '0'
529 | corr1: '0'
530 | corr10: '0'
531 | corr11: '0'
532 | corr12: '0'
533 | corr13: '0'
534 | corr14: '0'
535 | corr15: '0'
536 | corr16: '0'
537 | corr17: '0'
538 | corr18: '0'
539 | corr19: '0'
540 | corr2: '0'
541 | corr20: '0'
542 | corr21: '0'
543 | corr22: '0'
544 | corr23: '0'
545 | corr24: '0'
546 | corr25: '0'
547 | corr26: '0'
548 | corr27: '0'
549 | corr28: '0'
550 | corr29: '0'
551 | corr3: '0'
552 | corr30: '0'
553 | corr31: '0'
554 | corr4: '0'
555 | corr5: '0'
556 | corr6: '0'
557 | corr7: '0'
558 | corr8: '0'
559 | corr9: '0'
560 | dc_offset_mode0: '0'
561 | dc_offset_mode1: '0'
562 | dc_offset_mode10: '0'
563 | dc_offset_mode11: '0'
564 | dc_offset_mode12: '0'
565 | dc_offset_mode13: '0'
566 | dc_offset_mode14: '0'
567 | dc_offset_mode15: '0'
568 | dc_offset_mode16: '0'
569 | dc_offset_mode17: '0'
570 | dc_offset_mode18: '0'
571 | dc_offset_mode19: '0'
572 | dc_offset_mode2: '0'
573 | dc_offset_mode20: '0'
574 | dc_offset_mode21: '0'
575 | dc_offset_mode22: '0'
576 | dc_offset_mode23: '0'
577 | dc_offset_mode24: '0'
578 | dc_offset_mode25: '0'
579 | dc_offset_mode26: '0'
580 | dc_offset_mode27: '0'
581 | dc_offset_mode28: '0'
582 | dc_offset_mode29: '0'
583 | dc_offset_mode3: '0'
584 | dc_offset_mode30: '0'
585 | dc_offset_mode31: '0'
586 | dc_offset_mode4: '0'
587 | dc_offset_mode5: '0'
588 | dc_offset_mode6: '0'
589 | dc_offset_mode7: '0'
590 | dc_offset_mode8: '0'
591 | dc_offset_mode9: '0'
592 | freq0: freq
593 | freq1: 100e6
594 | freq10: 100e6
595 | freq11: 100e6
596 | freq12: 100e6
597 | freq13: 100e6
598 | freq14: 100e6
599 | freq15: 100e6
600 | freq16: 100e6
601 | freq17: 100e6
602 | freq18: 100e6
603 | freq19: 100e6
604 | freq2: 100e6
605 | freq20: 100e6
606 | freq21: 100e6
607 | freq22: 100e6
608 | freq23: 100e6
609 | freq24: 100e6
610 | freq25: 100e6
611 | freq26: 100e6
612 | freq27: 100e6
613 | freq28: 100e6
614 | freq29: 100e6
615 | freq3: 100e6
616 | freq30: 100e6
617 | freq31: 100e6
618 | freq4: 100e6
619 | freq5: 100e6
620 | freq6: 100e6
621 | freq7: 100e6
622 | freq8: 100e6
623 | freq9: 100e6
624 | gain0: rfgain
625 | gain1: '10'
626 | gain10: '10'
627 | gain11: '10'
628 | gain12: '10'
629 | gain13: '10'
630 | gain14: '10'
631 | gain15: '10'
632 | gain16: '10'
633 | gain17: '10'
634 | gain18: '10'
635 | gain19: '10'
636 | gain2: '10'
637 | gain20: '10'
638 | gain21: '10'
639 | gain22: '10'
640 | gain23: '10'
641 | gain24: '10'
642 | gain25: '10'
643 | gain26: '10'
644 | gain27: '10'
645 | gain28: '10'
646 | gain29: '10'
647 | gain3: '10'
648 | gain30: '10'
649 | gain31: '10'
650 | gain4: '10'
651 | gain5: '10'
652 | gain6: '10'
653 | gain7: '10'
654 | gain8: '10'
655 | gain9: '10'
656 | gain_mode0: 'False'
657 | gain_mode1: 'False'
658 | gain_mode10: 'False'
659 | gain_mode11: 'False'
660 | gain_mode12: 'False'
661 | gain_mode13: 'False'
662 | gain_mode14: 'False'
663 | gain_mode15: 'False'
664 | gain_mode16: 'False'
665 | gain_mode17: 'False'
666 | gain_mode18: 'False'
667 | gain_mode19: 'False'
668 | gain_mode2: 'False'
669 | gain_mode20: 'False'
670 | gain_mode21: 'False'
671 | gain_mode22: 'False'
672 | gain_mode23: 'False'
673 | gain_mode24: 'False'
674 | gain_mode25: 'False'
675 | gain_mode26: 'False'
676 | gain_mode27: 'False'
677 | gain_mode28: 'False'
678 | gain_mode29: 'False'
679 | gain_mode3: 'False'
680 | gain_mode30: 'False'
681 | gain_mode31: 'False'
682 | gain_mode4: 'False'
683 | gain_mode5: 'False'
684 | gain_mode6: 'False'
685 | gain_mode7: 'False'
686 | gain_mode8: 'False'
687 | gain_mode9: 'False'
688 | if_gain0: '20'
689 | if_gain1: '20'
690 | if_gain10: '20'
691 | if_gain11: '20'
692 | if_gain12: '20'
693 | if_gain13: '20'
694 | if_gain14: '20'
695 | if_gain15: '20'
696 | if_gain16: '20'
697 | if_gain17: '20'
698 | if_gain18: '20'
699 | if_gain19: '20'
700 | if_gain2: '20'
701 | if_gain20: '20'
702 | if_gain21: '20'
703 | if_gain22: '20'
704 | if_gain23: '20'
705 | if_gain24: '20'
706 | if_gain25: '20'
707 | if_gain26: '20'
708 | if_gain27: '20'
709 | if_gain28: '20'
710 | if_gain29: '20'
711 | if_gain3: '20'
712 | if_gain30: '20'
713 | if_gain31: '20'
714 | if_gain4: '20'
715 | if_gain5: '20'
716 | if_gain6: '20'
717 | if_gain7: '20'
718 | if_gain8: '20'
719 | if_gain9: '20'
720 | iq_balance_mode0: '0'
721 | iq_balance_mode1: '0'
722 | iq_balance_mode10: '0'
723 | iq_balance_mode11: '0'
724 | iq_balance_mode12: '0'
725 | iq_balance_mode13: '0'
726 | iq_balance_mode14: '0'
727 | iq_balance_mode15: '0'
728 | iq_balance_mode16: '0'
729 | iq_balance_mode17: '0'
730 | iq_balance_mode18: '0'
731 | iq_balance_mode19: '0'
732 | iq_balance_mode2: '0'
733 | iq_balance_mode20: '0'
734 | iq_balance_mode21: '0'
735 | iq_balance_mode22: '0'
736 | iq_balance_mode23: '0'
737 | iq_balance_mode24: '0'
738 | iq_balance_mode25: '0'
739 | iq_balance_mode26: '0'
740 | iq_balance_mode27: '0'
741 | iq_balance_mode28: '0'
742 | iq_balance_mode29: '0'
743 | iq_balance_mode3: '0'
744 | iq_balance_mode30: '0'
745 | iq_balance_mode31: '0'
746 | iq_balance_mode4: '0'
747 | iq_balance_mode5: '0'
748 | iq_balance_mode6: '0'
749 | iq_balance_mode7: '0'
750 | iq_balance_mode8: '0'
751 | iq_balance_mode9: '0'
752 | maxoutbuf: '0'
753 | minoutbuf: '0'
754 | nchan: '1'
755 | num_mboards: '1'
756 | sample_rate: samp_rate
757 | sync: sync
758 | time_source0: ''
759 | time_source1: ''
760 | time_source2: ''
761 | time_source3: ''
762 | time_source4: ''
763 | time_source5: ''
764 | time_source6: ''
765 | time_source7: ''
766 | type: fc32
767 | states:
768 | bus_sink: false
769 | bus_source: false
770 | bus_structure: null
771 | coordinate: [8, 212]
772 | rotation: 0
773 | state: enabled
774 | - name: outfile
775 | id: parameter
776 | parameters:
777 | alias: ''
778 | comment: ''
779 | hide: none
780 | label: Output File
781 | short_id: O
782 | type: str
783 | value: '"/tmp/logfile.csv"'
784 | states:
785 | bus_sink: false
786 | bus_source: false
787 | bus_structure: null
788 | coordinate: [1224, 32.0]
789 | rotation: 0
790 | state: true
791 | - name: qtgui_freq_sink_x_0
792 | id: qtgui_freq_sink_x
793 | parameters:
794 | affinity: ''
795 | alias: ''
796 | alpha1: '1.0'
797 | alpha10: '1.0'
798 | alpha2: '1.0'
799 | alpha3: '1.0'
800 | alpha4: '1.0'
801 | alpha5: '1.0'
802 | alpha6: '1.0'
803 | alpha7: '1.0'
804 | alpha8: '1.0'
805 | alpha9: '1.0'
806 | autoscale: 'False'
807 | average: '1.0'
808 | axislabels: 'True'
809 | bw: samp_rate
810 | color1: '"blue"'
811 | color10: '"dark blue"'
812 | color2: '"red"'
813 | color3: '"green"'
814 | color4: '"black"'
815 | color5: '"cyan"'
816 | color6: '"magenta"'
817 | color7: '"yellow"'
818 | color8: '"dark red"'
819 | color9: '"dark green"'
820 | comment: ''
821 | ctrlpanel: 'True'
822 | fc: freq
823 | fftsize: fftsize
824 | freqhalf: 'True'
825 | grid: 'True'
826 | gui_hint: tab0@0
827 | label: Relative Gain
828 | label1: ''
829 | label10: ''
830 | label2: ''
831 | label3: ''
832 | label4: ''
833 | label5: ''
834 | label6: ''
835 | label7: ''
836 | label8: ''
837 | label9: ''
838 | legend: 'True'
839 | maxoutbuf: '0'
840 | minoutbuf: '0'
841 | name: '""'
842 | nconnections: '1'
843 | showports: 'True'
844 | tr_chan: '0'
845 | tr_level: '0.0'
846 | tr_mode: qtgui.TRIG_MODE_FREE
847 | tr_tag: '""'
848 | type: complex
849 | units: dB
850 | update_time: '0.10'
851 | width1: '1'
852 | width10: '1'
853 | width2: '1'
854 | width3: '1'
855 | width4: '1'
856 | width5: '1'
857 | width6: '1'
858 | width7: '1'
859 | width8: '1'
860 | width9: '1'
861 | wintype: firdes.WIN_BLACKMAN_hARRIS
862 | ymax: '10'
863 | ymin: '-140'
864 | states:
865 | bus_sink: false
866 | bus_source: false
867 | bus_structure: null
868 | coordinate: [864, 360]
869 | rotation: 0
870 | state: enabled
871 | - name: qtgui_vector_sink_f_0
872 | id: qtgui_vector_sink_f
873 | parameters:
874 | affinity: ''
875 | alias: ''
876 | alpha1: '1.0'
877 | alpha10: '1.0'
878 | alpha2: '1.0'
879 | alpha3: '1.0'
880 | alpha4: '1.0'
881 | alpha5: '1.0'
882 | alpha6: '1.0'
883 | alpha7: '1.0'
884 | alpha8: '1.0'
885 | alpha9: '1.0'
886 | autoscale: 'True'
887 | average: '1.0'
888 | color1: '"blue"'
889 | color10: '"dark blue"'
890 | color2: '"red"'
891 | color3: '"green"'
892 | color4: '"black"'
893 | color5: '"cyan"'
894 | color6: '"magenta"'
895 | color7: '"yellow"'
896 | color8: '"dark red"'
897 | color9: '"dark green"'
898 | comment: ''
899 | grid: 'True'
900 | gui_hint: tab0@1
901 | label1: ''
902 | label10: ''
903 | label2: ''
904 | label3: ''
905 | label4: ''
906 | label5: ''
907 | label6: ''
908 | label7: ''
909 | label8: ''
910 | label9: ''
911 | maxoutbuf: '0'
912 | minoutbuf: '0'
913 | name: '""'
914 | nconnections: '2'
915 | ref_level: '0'
916 | showports: 'True'
917 | update_time: '0.10'
918 | vlen: fftsize
919 | width1: '1'
920 | width10: '1'
921 | width2: '1'
922 | width3: '1'
923 | width4: '1'
924 | width5: '1'
925 | width6: '1'
926 | width7: '1'
927 | width8: '1'
928 | width9: '1'
929 | x_axis_label: '"x-Axis"'
930 | x_start: freq-(samp_rate/2)
931 | x_step: samp_rate/fftsize
932 | x_units: '""'
933 | y_axis_label: '"y-Axis"'
934 | y_units: '""'
935 | ymax: '10'
936 | ymin: '-140'
937 | states:
938 | bus_sink: false
939 | bus_source: false
940 | bus_structure: null
941 | coordinate: [16, 636]
942 | rotation: 180
943 | state: enabled
944 | - name: runtime
945 | id: parameter
946 | parameters:
947 | alias: ''
948 | comment: ''
949 | hide: none
950 | label: ''
951 | short_id: R
952 | type: intx
953 | value: '3590'
954 | states:
955 | bus_sink: false
956 | bus_source: false
957 | bus_structure: null
958 | coordinate: [1120, 40.0]
959 | rotation: 0
960 | state: enabled
961 | - name: samp_rate
962 | id: parameter
963 | parameters:
964 | alias: ''
965 | comment: ''
966 | hide: none
967 | label: Sample Rate
968 | short_id: s
969 | type: eng_float
970 | value: 2e6
971 | states:
972 | bus_sink: false
973 | bus_source: false
974 | bus_structure: null
975 | coordinate: [760, 32]
976 | rotation: 0
977 | state: enabled
978 | - name: specmon_block
979 | id: epy_block
980 | parameters:
981 | _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\
982 | \ GRC will instantiate the first class it finds\nto get ports and parameters\
983 | \ of your block. The arguments to __init__ will\nbe the parameters. All of\
984 | \ them are required to have default values!\n\"\"\"\n\n#from __future__ import\
985 | \ print_function\nimport numpy as np\nfrom gnuradio import gr\nimport time\n\
986 | \n\nclass blk(gr.sync_block): # other base classes are basic_block, decim_block,\
987 | \ interp_block\n \"\"\"Specmon data analysis block. \n This block is the\
988 | \ improved version for specmon\n \"\"\"\n\n\t# Don't use \"logfile\" as varname\
989 | \ as it's reserved in GRC\n def __init__(self, fftsize=1024, start_state=0,\
990 | \ threshold=1.0, verbose=0, reportfile=\"/tmp/logfile.csv\"): # only default\
991 | \ arguments here\n \"\"\"arguments to this function show up as parameters\
992 | \ in GRC\"\"\"\n self.fftsize = fftsize\n self.start_state = start_state\n\
993 | \ self.threshold = threshold\n self.verbose = verbose\n \
994 | \ self.maxval = 0\n self.sumval = 0\n self.lowcounter = 1\n \
995 | \ self.reportfile = reportfile\n gr.sync_block.__init__(\n \
996 | \ self,\n name='Specmon2', # will show up in GRC\n \
997 | \ in_sig=[(np.float32,self.fftsize)],\n out_sig=None\n \
998 | \ )\n # Print startline\n self.outfile = open(reportfile, \"\
999 | a\")\n print (\"S,%.2f,H,%s,T,%.2f\" % ( time.time(), str(time.strftime(\"\
1000 | %H\")), threshold ), file=self.outfile, flush=True )\n \n def work(self,\
1001 | \ input_items, output_items):\n speclist = np.array(input_items[0][0])\n\
1002 | \ # Peak for max-value\n curval = np.amax(speclist)\n #\
1003 | \ Median for median noise level\n noiseval = np.median(speclist)\n \
1004 | \ if self.verbose == 1:\n #print (\"%.2f\" % curval)\n \
1005 | \ print (\"Current value: %.2f M %1.2f N %i S %.3f\" % ( curval, self.maxval,\
1006 | \ self.lowcounter, self.sumval ) )\n \n if curval > self.maxval:\n\
1007 | \ self.maxval = curval\n \n if curval > self.threshold\
1008 | \ and self.start_state == 0:\n # Signal triggers the threshold\n\
1009 | \ self.start_state = 1\n lowavg = self.sumval / self.lowcounter\n\
1010 | \ #print (\"A,%.2f,%.2f,\" % ( curval, time.time() ), end=\"\" )\n\
1011 | \ print (\"A,%.2f,%.2f,\" % ( lowavg, time.time() ), end=\"\", file=self.outfile\
1012 | \ )\n elif curval < self.threshold and self.start_state == 1:\n \
1013 | \ # Signal drops below threshold\n #print (\"U,%.2f,%.2f\"\
1014 | \ % ( curval, time.time() ), end=\"\\n\")\n print (\"U,%.2f,%.2f\"\
1015 | \ % ( self.maxval, time.time() ), end=\"\\n\", file=self.outfile, flush=True)\n\
1016 | \ self.start_state = 0\n self.sumval = 0\n \
1017 | \ self.lowcounter = 1\n self.maxval = 0 \n else:\n\
1018 | \ # Signal remains under threshold\n #self.sumval += curval\n\
1019 | \ self.sumval += noiseval\n self.lowcounter += 1\n\t\t\
1020 | \t\n \n return len(input_items[0])\n"
1021 | affinity: ''
1022 | alias: ''
1023 | comment: ''
1024 | fftsize: fftsize
1025 | maxoutbuf: '0'
1026 | minoutbuf: '0'
1027 | reportfile: outfile
1028 | start_state: start_state
1029 | threshold: threshold
1030 | verbose: verbose
1031 | states:
1032 | _io_cache: ('Specmon2', 'blk', [('fftsize', '1024'), ('start_state', '0'), ('threshold',
1033 | '1.0'), ('verbose', '0'), ('reportfile', "'/tmp/logfile.csv'")], [('0', 'float',
1034 | 1024)], [], 'Specmon data analysis block. \n This block is the improved version
1035 | for specmon\n ', ['fftsize', 'reportfile', 'start_state', 'threshold', 'verbose'])
1036 | bus_sink: false
1037 | bus_source: false
1038 | bus_structure: null
1039 | coordinate: [40, 472.0]
1040 | rotation: 180
1041 | state: enabled
1042 | - name: tab0
1043 | id: qtgui_tab_widget
1044 | parameters:
1045 | alias: ''
1046 | comment: ''
1047 | gui_hint: ''
1048 | label0: freq sink
1049 | label1: vector sink
1050 | label10: Tab 10
1051 | label11: Tab 11
1052 | label12: Tab 12
1053 | label13: Tab 13
1054 | label14: Tab 14
1055 | label15: Tab 15
1056 | label16: Tab 16
1057 | label17: Tab 17
1058 | label18: Tab 18
1059 | label19: Tab 19
1060 | label2: Tab 2
1061 | label3: Tab 3
1062 | label4: Tab 4
1063 | label5: Tab 5
1064 | label6: Tab 6
1065 | label7: Tab 7
1066 | label8: Tab 8
1067 | label9: Tab 9
1068 | num_tabs: '2'
1069 | states:
1070 | bus_sink: false
1071 | bus_source: false
1072 | bus_structure: null
1073 | coordinate: [296, 336.0]
1074 | rotation: 0
1075 | state: enabled
1076 | - name: verbose
1077 | id: parameter
1078 | parameters:
1079 | alias: ''
1080 | comment: ''
1081 | hide: none
1082 | label: Print verbose values
1083 | short_id: v
1084 | type: intx
1085 | value: '0'
1086 | states:
1087 | bus_sink: false
1088 | bus_source: false
1089 | bus_structure: null
1090 | coordinate: [912, 32]
1091 | rotation: 0
1092 | state: enabled
1093 |
1094 | connections:
1095 | - [blocks_add_xx_0, '0', qtgui_vector_sink_f_0, '0']
1096 | - [blocks_add_xx_0, '0', specmon_block, '0']
1097 | - [blocks_complex_to_mag_squared_0, '0', blocks_integrate_xx_0, '0']
1098 | - [blocks_file_source_0, '0', blocks_add_xx_0, '1']
1099 | - [blocks_head_0, '0', blocks_moving_average_xx_0, '0']
1100 | - [blocks_head_0, '0', blocks_sub_xx_0, '0']
1101 | - [blocks_integrate_xx_0, '0', blocks_multiply_const_vxx_0, '0']
1102 | - [blocks_moving_average_xx_0, '0', blocks_sub_xx_0, '1']
1103 | - [blocks_multiply_const_vxx_0, '0', blocks_nlog10_ff_0, '0']
1104 | - [blocks_nlog10_ff_0, '0', blocks_add_xx_0, '0']
1105 | - [blocks_stream_to_vector_0, '0', fft_vxx_0, '0']
1106 | - [blocks_sub_xx_0, '0', blocks_stream_to_vector_0, '0']
1107 | - [blocks_sub_xx_0, '0', qtgui_freq_sink_x_0, '0']
1108 | - [blocks_vector_source_x_0, '0', qtgui_vector_sink_f_0, '1']
1109 | - [fft_vxx_0, '0', blocks_complex_to_mag_squared_0, '0']
1110 | - [osmosdr_source_0, '0', blocks_head_0, '0']
1111 |
1112 | metadata:
1113 | file_format: 1
1114 |
--------------------------------------------------------------------------------
/specmon2_replay.grc:
--------------------------------------------------------------------------------
1 | options:
2 | parameters:
3 | author: PE1RIK
4 | category: '[GRC Hier Blocks]'
5 | cmake_opt: ''
6 | comment: ''
7 | copyright: ''
8 | description: ''
9 | gen_cmake: 'On'
10 | gen_linking: dynamic
11 | generate_options: qt_gui
12 | hier_block_src_path: '.:'
13 | id: specmon2_replay
14 | max_nouts: '0'
15 | output_language: python
16 | placement: (0,0)
17 | qt_qss_theme: ''
18 | realtime_scheduling: ''
19 | run: 'True'
20 | run_command: '{python} -u {filename}'
21 | run_options: prompt
22 | sizing_mode: fixed
23 | thread_safe_setters: ''
24 | title: ''
25 | window_size: ''
26 | states:
27 | bus_sink: false
28 | bus_source: false
29 | bus_structure: null
30 | coordinate: [8, 8]
31 | rotation: 0
32 | state: enabled
33 |
34 | blocks:
35 | - name: fftsize
36 | id: variable
37 | parameters:
38 | comment: ''
39 | value: '2048'
40 | states:
41 | bus_sink: false
42 | bus_source: false
43 | bus_structure: null
44 | coordinate: [280, 40]
45 | rotation: 0
46 | state: enabled
47 | - name: freq
48 | id: variable
49 | parameters:
50 | comment: ''
51 | value: 145e6
52 | states:
53 | bus_sink: false
54 | bus_source: false
55 | bus_structure: null
56 | coordinate: [528, 40]
57 | rotation: 0
58 | state: enabled
59 | - name: samp_rate
60 | id: variable
61 | parameters:
62 | comment: ''
63 | value: 2e6
64 | states:
65 | bus_sink: false
66 | bus_source: false
67 | bus_structure: null
68 | coordinate: [408, 40]
69 | rotation: 0
70 | state: enabled
71 | - name: threshold
72 | id: variable_qtgui_range
73 | parameters:
74 | comment: ''
75 | gui_hint: ''
76 | label: ''
77 | min_len: '200'
78 | orient: Qt.Horizontal
79 | rangeType: float
80 | start: '0'
81 | step: '.1'
82 | stop: '20'
83 | value: '8.0'
84 | widget: counter_slider
85 | states:
86 | bus_sink: false
87 | bus_source: false
88 | bus_structure: null
89 | coordinate: [672, 48]
90 | rotation: 0
91 | state: enabled
92 | - name: trate
93 | id: variable_config
94 | parameters:
95 | comment: ''
96 | config_file: /tmp/test.conf
97 | option: trate
98 | section: main
99 | type: int
100 | value: '1'
101 | writeback: None
102 | states:
103 | bus_sink: false
104 | bus_source: false
105 | bus_structure: null
106 | coordinate: [64, 444]
107 | rotation: 0
108 | state: enabled
109 | - name: blocks_add_xx_0
110 | id: blocks_add_xx
111 | parameters:
112 | affinity: ''
113 | alias: ''
114 | comment: ''
115 | maxoutbuf: '0'
116 | minoutbuf: '0'
117 | num_inputs: '2'
118 | type: float
119 | vlen: fftsize
120 | states:
121 | bus_sink: false
122 | bus_source: false
123 | bus_structure: null
124 | coordinate: [736, 336]
125 | rotation: 0
126 | state: enabled
127 | - name: blocks_file_source_0
128 | id: blocks_file_source
129 | parameters:
130 | affinity: ''
131 | alias: ''
132 | begin_tag: pmt.PMT_NIL
133 | comment: Vector source from filesink of specmon2
134 | file: /tmp/210928-1510-145000000-2000000-2048.pvector
135 | length: '0'
136 | maxoutbuf: '0'
137 | minoutbuf: '0'
138 | offset: '0'
139 | repeat: 'False'
140 | type: float
141 | vlen: fftsize
142 | states:
143 | bus_sink: false
144 | bus_source: false
145 | bus_structure: null
146 | coordinate: [176, 200]
147 | rotation: 0
148 | state: enabled
149 | - name: blocks_file_source_1
150 | id: blocks_file_source
151 | parameters:
152 | affinity: ''
153 | alias: ''
154 | begin_tag: pmt.PMT_NIL
155 | comment: ''
156 | file: /home/bart/grc/210928-145M-2e6-20g-2048-0.cal
157 | length: '0'
158 | maxoutbuf: '0'
159 | minoutbuf: '0'
160 | offset: '0'
161 | repeat: 'True'
162 | type: float
163 | vlen: fftsize
164 | states:
165 | bus_sink: false
166 | bus_source: false
167 | bus_structure: null
168 | coordinate: [408, 408]
169 | rotation: 0
170 | state: enabled
171 | - name: blocks_throttle_0
172 | id: blocks_throttle
173 | parameters:
174 | affinity: ''
175 | alias: ''
176 | comment: ''
177 | ignoretag: 'True'
178 | maxoutbuf: '0'
179 | minoutbuf: '0'
180 | samples_per_second: trate
181 | type: float
182 | vlen: fftsize
183 | states:
184 | bus_sink: false
185 | bus_source: false
186 | bus_structure: null
187 | coordinate: [424, 216]
188 | rotation: 0
189 | state: enabled
190 | - name: blocks_vector_source_x_0
191 | id: blocks_vector_source_x
192 | parameters:
193 | affinity: ''
194 | alias: ''
195 | comment: ''
196 | maxoutbuf: '0'
197 | minoutbuf: '0'
198 | repeat: 'True'
199 | tags: '[]'
200 | type: float
201 | vector: '[threshold]*fftsize'
202 | vlen: fftsize
203 | states:
204 | bus_sink: false
205 | bus_source: false
206 | bus_structure: null
207 | coordinate: [1048, 440]
208 | rotation: 180
209 | state: enabled
210 | - name: note_0
211 | id: note
212 | parameters:
213 | alias: ''
214 | comment: 'content of configfile /tmp/test.conf:
215 |
216 |
217 | [main]
218 |
219 | trate = 100'
220 | note: Reminders
221 | states:
222 | bus_sink: false
223 | bus_source: false
224 | bus_structure: null
225 | coordinate: [72, 616]
226 | rotation: 0
227 | state: enabled
228 | - name: qtgui_vector_sink_f_0
229 | id: qtgui_vector_sink_f
230 | parameters:
231 | affinity: ''
232 | alias: ''
233 | alpha1: '1.0'
234 | alpha10: '1.0'
235 | alpha2: '1.0'
236 | alpha3: '1.0'
237 | alpha4: '1.0'
238 | alpha5: '1.0'
239 | alpha6: '1.0'
240 | alpha7: '1.0'
241 | alpha8: '1.0'
242 | alpha9: '1.0'
243 | autoscale: 'False'
244 | average: '1.0'
245 | color1: '"blue"'
246 | color10: '"dark blue"'
247 | color2: '"red"'
248 | color3: '"green"'
249 | color4: '"black"'
250 | color5: '"cyan"'
251 | color6: '"magenta"'
252 | color7: '"yellow"'
253 | color8: '"dark red"'
254 | color9: '"dark green"'
255 | comment: 'X-start: freq-(samp_rate/2)
256 |
257 | X-step: samp_rate/fftsize'
258 | grid: 'True'
259 | gui_hint: ''
260 | label1: ''
261 | label10: ''
262 | label2: ''
263 | label3: ''
264 | label4: ''
265 | label5: ''
266 | label6: ''
267 | label7: ''
268 | label8: ''
269 | label9: ''
270 | maxoutbuf: '0'
271 | minoutbuf: '0'
272 | name: '""'
273 | nconnections: '3'
274 | ref_level: '0'
275 | showports: 'True'
276 | update_time: '0.10'
277 | vlen: fftsize
278 | width1: '1'
279 | width10: '1'
280 | width2: '1'
281 | width3: '1'
282 | width4: '1'
283 | width5: '1'
284 | width6: '1'
285 | width7: '1'
286 | width8: '1'
287 | width9: '1'
288 | x_axis_label: '"x-Axis"'
289 | x_start: freq-(samp_rate/2)
290 | x_step: samp_rate/fftsize
291 | x_units: '""'
292 | y_axis_label: '"y-Axis"'
293 | y_units: '""'
294 | ymax: '10'
295 | ymin: '0'
296 | states:
297 | bus_sink: false
298 | bus_source: false
299 | bus_structure: null
300 | coordinate: [1048, 196]
301 | rotation: 0
302 | state: enabled
303 |
304 | connections:
305 | - [blocks_add_xx_0, '0', qtgui_vector_sink_f_0, '1']
306 | - [blocks_file_source_0, '0', blocks_throttle_0, '0']
307 | - [blocks_file_source_1, '0', blocks_add_xx_0, '1']
308 | - [blocks_throttle_0, '0', blocks_add_xx_0, '0']
309 | - [blocks_throttle_0, '0', qtgui_vector_sink_f_0, '0']
310 | - [blocks_vector_source_x_0, '0', qtgui_vector_sink_f_0, '2']
311 |
312 | metadata:
313 | file_format: 1
314 |
--------------------------------------------------------------------------------
/specreceive.grc:
--------------------------------------------------------------------------------
1 | options:
2 | parameters:
3 | author: PE1RIK
4 | category: '[GRC Hier Blocks]'
5 | cmake_opt: ''
6 | comment: ''
7 | copyright: ''
8 | description: ''
9 | gen_cmake: 'On'
10 | gen_linking: dynamic
11 | generate_options: qt_gui
12 | hier_block_src_path: '.:'
13 | id: specreceive
14 | max_nouts: '0'
15 | output_language: python
16 | placement: (0,0)
17 | qt_qss_theme: ''
18 | realtime_scheduling: ''
19 | run: 'True'
20 | run_command: '{python} -u {filename}'
21 | run_options: prompt
22 | sizing_mode: fixed
23 | thread_safe_setters: ''
24 | title: Specmon_Receiver
25 | window_size: ''
26 | states:
27 | bus_sink: false
28 | bus_source: false
29 | bus_structure: null
30 | coordinate: [8, 8]
31 | rotation: 0
32 | state: enabled
33 |
34 | blocks:
35 | - name: threshold
36 | id: variable_qtgui_range
37 | parameters:
38 | comment: ''
39 | gui_hint: ''
40 | label: ''
41 | min_len: '200'
42 | orient: Qt.Horizontal
43 | rangeType: float
44 | start: '0'
45 | step: '.1'
46 | stop: '20'
47 | value: '8.0'
48 | widget: counter_slider
49 | states:
50 | bus_sink: false
51 | bus_source: false
52 | bus_structure: null
53 | coordinate: [704, 40.0]
54 | rotation: 0
55 | state: enabled
56 | - name: blocks_add_const_vxx_0
57 | id: blocks_add_const_vxx
58 | parameters:
59 | affinity: ''
60 | alias: ''
61 | comment: 'Constant is a value for correction to real dBm.
62 |
63 | Only to be used after calibration measurement.'
64 | const: ([calconst]*fftsize)
65 | maxoutbuf: '0'
66 | minoutbuf: '0'
67 | type: float
68 | vlen: fftsize
69 | states:
70 | bus_sink: false
71 | bus_source: false
72 | bus_structure: null
73 | coordinate: [320, 272.0]
74 | rotation: 0
75 | state: true
76 | - name: blocks_vector_source_x_0
77 | id: blocks_vector_source_x
78 | parameters:
79 | affinity: ''
80 | alias: ''
81 | comment: ''
82 | maxoutbuf: '0'
83 | minoutbuf: '0'
84 | repeat: 'True'
85 | tags: '[]'
86 | type: float
87 | vector: '[threshold+calconst]*fftsize'
88 | vlen: fftsize
89 | states:
90 | bus_sink: false
91 | bus_source: false
92 | bus_structure: null
93 | coordinate: [840, 368.0]
94 | rotation: 180
95 | state: disabled
96 | - name: blocks_vector_to_stream_0
97 | id: blocks_vector_to_stream
98 | parameters:
99 | affinity: ''
100 | alias: ''
101 | comment: ''
102 | maxoutbuf: '0'
103 | minoutbuf: '0'
104 | num_items: fftsize
105 | type: float
106 | vlen: '1'
107 | states:
108 | bus_sink: false
109 | bus_source: false
110 | bus_structure: null
111 | coordinate: [544, 488.0]
112 | rotation: 0
113 | state: true
114 | - name: calconst
115 | id: parameter
116 | parameters:
117 | alias: ''
118 | comment: ''
119 | hide: none
120 | label: calibration-constant
121 | short_id: c
122 | type: eng_float
123 | value: '-132'
124 | states:
125 | bus_sink: false
126 | bus_source: false
127 | bus_structure: null
128 | coordinate: [864, 44.0]
129 | rotation: 0
130 | state: true
131 | - name: fftsize
132 | id: parameter
133 | parameters:
134 | alias: ''
135 | comment: ''
136 | hide: none
137 | label: fft-size
138 | short_id: F
139 | type: intx
140 | value: '4096'
141 | states:
142 | bus_sink: false
143 | bus_source: false
144 | bus_structure: null
145 | coordinate: [280, 36.0]
146 | rotation: 0
147 | state: true
148 | - name: freq
149 | id: parameter
150 | parameters:
151 | alias: ''
152 | comment: ''
153 | hide: none
154 | label: Frequency
155 | short_id: f
156 | type: eng_float
157 | value: 48e6
158 | states:
159 | bus_sink: false
160 | bus_source: false
161 | bus_structure: null
162 | coordinate: [552, 36.0]
163 | rotation: 0
164 | state: true
165 | - name: qtgui_time_raster_sink_x_0
166 | id: qtgui_time_raster_sink_x
167 | parameters:
168 | affinity: ''
169 | alias: ''
170 | alpha1: '1.0'
171 | alpha10: '1.0'
172 | alpha2: '1.0'
173 | alpha3: '1.0'
174 | alpha4: '1.0'
175 | alpha5: '1.0'
176 | alpha6: '1.0'
177 | alpha7: '1.0'
178 | alpha8: '1.0'
179 | alpha9: '1.0'
180 | axislabels: 'False'
181 | color1: '0'
182 | color10: '0'
183 | color2: '0'
184 | color3: '0'
185 | color4: '0'
186 | color5: '0'
187 | color6: '0'
188 | color7: '0'
189 | color8: '0'
190 | color9: '0'
191 | comment: ''
192 | grid: 'True'
193 | gui_hint: tabje@1
194 | label1: ''
195 | label10: ''
196 | label2: ''
197 | label3: ''
198 | label4: ''
199 | label5: ''
200 | label6: ''
201 | label7: ''
202 | label8: ''
203 | label9: ''
204 | mult: '[]'
205 | name: '""'
206 | ncols: fftsize
207 | nconnections: '1'
208 | nrows: '500'
209 | offset: '[]'
210 | samp_rate: '5'
211 | type: float
212 | update_time: '0.10'
213 | zmax: '-110'
214 | zmin: '-130'
215 | states:
216 | bus_sink: false
217 | bus_source: false
218 | bus_structure: null
219 | coordinate: [808, 520.0]
220 | rotation: 0
221 | state: true
222 | - name: qtgui_vector_sink_f_0
223 | id: qtgui_vector_sink_f
224 | parameters:
225 | affinity: ''
226 | alias: ''
227 | alpha1: '1.0'
228 | alpha10: '1.0'
229 | alpha2: '1.0'
230 | alpha3: '1.0'
231 | alpha4: '1.0'
232 | alpha5: '1.0'
233 | alpha6: '1.0'
234 | alpha7: '1.0'
235 | alpha8: '1.0'
236 | alpha9: '1.0'
237 | autoscale: 'False'
238 | average: '1.0'
239 | color1: '"blue"'
240 | color10: '"dark blue"'
241 | color2: '"red"'
242 | color3: '"green"'
243 | color4: '"black"'
244 | color5: '"cyan"'
245 | color6: '"magenta"'
246 | color7: '"yellow"'
247 | color8: '"dark red"'
248 | color9: '"dark green"'
249 | comment: 'X-start: freq-(samp_rate/2)
250 |
251 | X-step: samp_rate/fftsize'
252 | grid: 'False'
253 | gui_hint: tabje@0
254 | label1: Original
255 | label10: ''
256 | label2: Threshold
257 | label3: Sorted
258 | label4: ''
259 | label5: ''
260 | label6: ''
261 | label7: ''
262 | label8: ''
263 | label9: ''
264 | maxoutbuf: '0'
265 | minoutbuf: '0'
266 | name: '""'
267 | nconnections: '3'
268 | ref_level: '0'
269 | showports: 'True'
270 | update_time: '0.10'
271 | vlen: fftsize
272 | width1: '1'
273 | width10: '1'
274 | width2: '1'
275 | width3: '1'
276 | width4: '1'
277 | width5: '1'
278 | width6: '1'
279 | width7: '1'
280 | width8: '1'
281 | width9: '1'
282 | x_axis_label: '"x-Axis"'
283 | x_start: freq-(samp_rate/2)
284 | x_step: samp_rate/fftsize
285 | x_units: '""'
286 | y_axis_label: '"y-Axis"'
287 | y_units: '""'
288 | ymax: '-110'
289 | ymin: '-130'
290 | states:
291 | bus_sink: false
292 | bus_source: false
293 | bus_structure: null
294 | coordinate: [848, 184.0]
295 | rotation: 0
296 | state: enabled
297 | - name: remote
298 | id: parameter
299 | parameters:
300 | alias: ''
301 | comment: 'Host to connect to. Format:
302 |
303 | tcp://:'
304 | hide: none
305 | label: remote-host
306 | short_id: r
307 | type: str
308 | value: tcp://sigint:50001
309 | states:
310 | bus_sink: false
311 | bus_source: false
312 | bus_structure: null
313 | coordinate: [64, 164.0]
314 | rotation: 0
315 | state: true
316 | - name: samp_rate
317 | id: parameter
318 | parameters:
319 | alias: ''
320 | comment: ''
321 | hide: none
322 | label: Sample-Rate
323 | short_id: s
324 | type: eng_float
325 | value: 2.5e6
326 | states:
327 | bus_sink: false
328 | bus_source: false
329 | bus_structure: null
330 | coordinate: [408, 36.0]
331 | rotation: 0
332 | state: true
333 | - name: tabje
334 | id: qtgui_tab_widget
335 | parameters:
336 | alias: ''
337 | comment: ''
338 | gui_hint: ''
339 | label0: Spectrum
340 | label1: Waterfall
341 | label10: Tab 10
342 | label11: Tab 11
343 | label12: Tab 12
344 | label13: Tab 13
345 | label14: Tab 14
346 | label15: Tab 15
347 | label16: Tab 16
348 | label17: Tab 17
349 | label18: Tab 18
350 | label19: Tab 19
351 | label2: Tab 2
352 | label3: Tab 3
353 | label4: Tab 4
354 | label5: Tab 5
355 | label6: Tab 6
356 | label7: Tab 7
357 | label8: Tab 8
358 | label9: Tab 9
359 | num_tabs: '2'
360 | states:
361 | bus_sink: false
362 | bus_source: false
363 | bus_structure: null
364 | coordinate: [224, 504.0]
365 | rotation: 0
366 | state: true
367 | - name: vector_sorter
368 | id: epy_block
369 | parameters:
370 | _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\
371 | \ GRC will instantiate the first class it finds\nto get ports and parameters\
372 | \ of your block. The arguments to __init__ will\nbe the parameters. All of\
373 | \ them are required to have default values!\n\"\"\"\n\nimport numpy as np\n\
374 | from gnuradio import gr\n\n\nclass blk(gr.sync_block): # other base classes\
375 | \ are basic_block, decim_block, interp_block\n \"\"\"Vector Sort And Threshold\
376 | \ \n \n This block does 2 things:\n - Sort a vector with numpy. Output\
377 | \ this vector on port 0\n \n - Calculate the median (50%) and add the\
378 | \ threshold. Output a vector on port 1.\n \n \"\"\"\n\n def __init__(self,\
379 | \ fftsize=4096, threshold=8.0): # only default arguments here\n \"\"\
380 | \"arguments to this function show up as parameters in GRC\"\"\"\n self.threshold\
381 | \ = threshold\n self.fftsize = fftsize\n gr.sync_block.__init__(\n\
382 | \ self,\n name='Vector Sort And Threshold', # will show\
383 | \ up in GRC\n in_sig=[(np.float32,fftsize)],\n out_sig=[(np.float32,fftsize),(np.float32,fftsize)]\n\
384 | \ )\n # if an attribute with the same name as a parameter is found,\n\
385 | \ # a callback is registered (properties work, too).\n #self.example_param\
386 | \ = example_param\n\n def work(self, input_items, output_items):\n \
387 | \ # Sort the list\n sortlist = np.sort(input_items[0])\n # Output\
388 | \ the sorted list on output 0\n output_items[0][:] = sortlist\n \
389 | \ # Determine the median\n vecmedian = np.median(sortlist[:(int(self.fftsize/2))])\n\
390 | \ # Output the calculated threshold as vector on output 1\n output_items[1][:]\
391 | \ = [self.threshold + vecmedian]*self.fftsize\n return len(output_items[0])\n"
392 | affinity: ''
393 | alias: ''
394 | comment: ''
395 | fftsize: fftsize
396 | maxoutbuf: '0'
397 | minoutbuf: '0'
398 | threshold: threshold
399 | states:
400 | _io_cache: ('Vector Sort And Threshold', 'blk', [('fftsize', '4096'), ('threshold',
401 | '8.0')], [('0', 'float', 4096)], [('0', 'float', 4096), ('1', 'float', 4096)],
402 | 'Vector Sort And Threshold \n \n This block does 2 things:\n - Sort
403 | a vector with numpy. Output this vector on port 0\n \n - Calculate the
404 | median (50%) and add the threshold. Output a vector on port 1.\n \n ',
405 | ['fftsize', 'threshold'])
406 | bus_sink: false
407 | bus_source: false
408 | bus_structure: null
409 | coordinate: [600, 344.0]
410 | rotation: 0
411 | state: true
412 | - name: zeromq_sub_source_0
413 | id: zeromq_sub_source
414 | parameters:
415 | address: remote
416 | affinity: ''
417 | alias: ''
418 | comment: ''
419 | hwm: '-1'
420 | maxoutbuf: '0'
421 | minoutbuf: '0'
422 | pass_tags: 'False'
423 | timeout: '100'
424 | type: float
425 | vlen: fftsize
426 | states:
427 | bus_sink: false
428 | bus_source: false
429 | bus_structure: null
430 | coordinate: [56, 332.0]
431 | rotation: 0
432 | state: true
433 |
434 | connections:
435 | - [blocks_add_const_vxx_0, '0', blocks_vector_to_stream_0, '0']
436 | - [blocks_add_const_vxx_0, '0', qtgui_vector_sink_f_0, '0']
437 | - [blocks_add_const_vxx_0, '0', vector_sorter, '0']
438 | - [blocks_vector_source_x_0, '0', qtgui_vector_sink_f_0, '1']
439 | - [blocks_vector_to_stream_0, '0', qtgui_time_raster_sink_x_0, '0']
440 | - [vector_sorter, '0', qtgui_vector_sink_f_0, '2']
441 | - [vector_sorter, '1', qtgui_vector_sink_f_0, '1']
442 | - [zeromq_sub_source_0, '0', blocks_add_const_vxx_0, '0']
443 |
444 | metadata:
445 | file_format: 1
446 |
--------------------------------------------------------------------------------
/testspec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | #
3 | # Description: Tool to parse the logfiles to a daily log
4 | #
5 | # Author: Bart Somers PE1RIK
6 |
7 | from datetime import datetime
8 | import argparse
9 |
10 | # Parse the arguments
11 | parser = argparse.ArgumentParser()
12 | parser.add_argument('-i', '--infile', type=str, help='Filename with output from specmon', required=True)
13 | parser.add_argument('-o', '--outfile', type=str, help='Filename where to put output', required=True)
14 | parser.add_argument('-v', '--version', type=int, help='Outputformat. use 2 for new format', required=False)
15 | parser.add_argument('-r', '--runtime', type=int, help='Runtime in seconds if not 3600', required=False)
16 | args = parser.parse_args()
17 |
18 | fhandler = open (args.infile, "r")
19 | outhandler = open (args.outfile, "a")
20 |
21 | # Check if other runtime is given
22 | if args.runtime:
23 | runtime = args.runtime
24 | else:
25 | runtime = 3600
26 |
27 | # Pre-define variables
28 | totaalverschil = 0
29 | start_uur = 0
30 | threshold = 0
31 | counter = 0
32 | dom = 0
33 | maxval = 0
34 | lastunder = 0
35 | lowsum = 0
36 |
37 | # Proces line by line
38 | for line in fhandler:
39 | array = line.split(',')
40 | if len(array) > 5:
41 | if array[0] == "A":
42 | verschil = float(array[5]) - float(array[2])
43 | lastunder = float(array[5])
44 | totaalverschil += verschil
45 | counter +=1
46 | # Determine the max of measurement over the hour
47 | if float(array[4]) > maxval:
48 | maxval = float(array[4])
49 | # Sum the lowavg
50 | lowsum += float(array[1])
51 | elif array[0] == "S":
52 | # Startup-line
53 | start_uur = array[3]
54 | threshold = array[5].rstrip()
55 | # Force the lastunder to be the end-time.
56 | lastunder = float(array[1]) + float(runtime)
57 | date_time = datetime.fromtimestamp(float(array[1]))
58 | dom = date_time.strftime("%d")
59 | dow = date_time.strftime("%w")
60 | elif array[0] == "A" and len(array) < 5:
61 | # Probably no "Under threshold" written
62 | verschil = abs(float(array[2]) - float(lastunder))
63 | totaalverschil += verschil
64 | counter +=1
65 |
66 | # Calculate the percentage
67 | percentage = totaalverschil / (runtime/100)
68 |
69 | if counter == 0:
70 | average_open = 0
71 | average_low = 0
72 | else:
73 | average_open = totaalverschil / counter
74 | average_low = lowsum / counter
75 |
76 | if args.version == 2:
77 | # Print new version string
78 | print ('%s,%.2f,%.2f,%s,%i,%s,%.2f,%.2f,%s,%.2f' % ( start_uur, totaalverschil, percentage, threshold, counter, dom, average_open, maxval, dow, average_low ), file=outhandler )
79 | else:
80 | # Print the original string
81 | print ('U %s V %.2f P %.2f T %s O %i D %s A %.2f M %.2f W %s L %.2f' % ( start_uur, totaalverschil, percentage, threshold, counter, dom, average_open, maxval, dow, average_low ), file=outhandler )
82 |
83 | # Closing up
84 | fhandler.close()
85 | outhandler.close()
86 |
87 | exit(0)
88 |
--------------------------------------------------------------------------------
/weekgraph:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | INPUT=$1
3 | gnuplot <<- EOF
4 | set terminal png size 1280,768
5 | set output '$INPUT-week.png'
6 | set xrange [0:23]
7 | set xlabel "Hour"
8 | set ylabel "Day"
9 | set cblabel "Percentage of usage"
10 | unset key
11 | load 'gnuplot-palettes/reds.pal'
12 | plot "$INPUT" using 2:12:6 with image pixels
13 | EOF
14 |
--------------------------------------------------------------------------------