├── .gitignore ├── COPYING ├── ChangeLog ├── README.md ├── example-output.txt ├── example.py └── pyviscalib ├── __init__.py └── visca.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | PyVisca 0.01: 2 | 3 | * initial release 4 | * proof of concept 5 | * no error handling 6 | * basic functionality for SONY EVI-D100P 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PyVisca 2 | ======= 3 | 4 | Reimplementation of libvisca in python to control Cameras via the serial line visca protocol 5 | 6 | 7 | Why? 8 | ---- 9 | 10 | I found a SONY EVI-D100P in the trash and decided to play around with it. 11 | 12 | The camera has analog video output and a serial port for remote control using the Visca protocol. 13 | 14 | I found the protocol being publicly documented by Sony in a camera manual and a C implementation 15 | of that protocol at http://sourceforge.net/projects/libvisca/ - but I wanted an easier solution 16 | so I started implementing the commandset my camera offers in python. 17 | 18 | 19 | Status 20 | ------ 21 | 22 | Currently the basic functions all work but there is no error handling yet as at this stage it was 23 | just a proof of concept. I plan on adding this and make it a full featured implementation, at leat 24 | for my camera. 25 | 26 | The error handling might make some changes neccessary due to the fact that some commands are being executed 27 | asynchronously and the camera returns an ACK when the command was accepted and another message when it was 28 | completed (e.g. tilting, panning). This will require some changes so don't expect anything to be stable. 29 | 30 | As this is a side project these changes are not highest priority. 31 | -------------------------------------------------------------------------------- /example-output.txt: -------------------------------------------------------------------------------- 1 | ----- 2 | packet (sent) [0 => *] len=4: 883001ff 3 | QQ.........: 30 4 | RR.........: 01 5 | Data.......: None 6 | ----- 7 | packet (recv) [0 => *] len=4: 883002ff 8 | QQ.........: 30 9 | RR.........: 02 10 | Data.......: None 11 | debug: found 1 devices on the bus 12 | ----- 13 | packet (sent) [0 => *] len=5: 88010001ff 14 | QQ.........: 01 15 | (Command) 16 | RR.........: 00 17 | (Interface) 18 | Data.......: 01 19 | ----- 20 | packet (recv) [0 => *] len=5: 88010001ff 21 | QQ.........: 01 22 | (Command) 23 | RR.........: 00 24 | (Interface) 25 | Data.......: 01 26 | debug: all interfaces clear 27 | ----- 28 | packet (sent) [0 => 1] len=6: 8101040002ff 29 | QQ.........: 01 30 | (Command) 31 | RR.........: 04 32 | (Camera [1]) 33 | Data.......: 0002 34 | ----- 35 | packet (recv) [1 => 0] len=3: 9041ff 36 | QQ.........: 41 37 | Data.......: None 38 | packet: ACK for socket 01 39 | ----- 40 | packet (recv: ignored) [1 => 0] len=3: 9051ff 41 | QQ.........: 51 42 | Data.......: None 43 | packet: COMPLETION for socket 01 44 | ----- 45 | packet (sent) [0 => 1] len=9: 8101044000000002ff 46 | QQ.........: 01 47 | (Command) 48 | RR.........: 04 49 | (Camera [1]) 50 | Data.......: 4000000002 51 | ----- 52 | packet (recv) [1 => 0] len=3: 9041ff 53 | QQ.........: 41 54 | Data.......: None 55 | packet: ACK for socket 01 56 | ----- 57 | packet (recv: ignored) [1 => 0] len=3: 9051ff 58 | QQ.........: 51 59 | Data.......: None 60 | packet: COMPLETION for socket 01 61 | ----- 62 | packet (sent) [0 => 1] len=6: 8101060602ff 63 | QQ.........: 01 64 | (Command) 65 | RR.........: 06 66 | (Pan/Tilter) 67 | Data.......: 0602 68 | ----- 69 | packet (recv) [1 => 0] len=3: 9041ff 70 | QQ.........: 41 71 | Data.......: None 72 | packet: ACK for socket 01 73 | DEBUG: ABS POS TO -1440/-360 74 | ----- 75 | packet (recv: ignored) [1 => 0] len=3: 9051ff 76 | QQ.........: 51 77 | Data.......: None 78 | packet: COMPLETION for socket 01 79 | ----- 80 | packet (sent) [0 => 1] len=15: 8101060214180f0a06000f0e0908ff 81 | QQ.........: 01 82 | (Command) 83 | RR.........: 06 84 | (Pan/Tilter) 85 | Data.......: 0214180f0a06000f0e0908 86 | ----- 87 | packet (recv) [1 => 0] len=3: 9041ff 88 | QQ.........: 41 89 | Data.......: None 90 | packet: ACK for socket 01 91 | DEBUG: cam_memory command 92 | ----- 93 | packet (recv: ignored) [1 => 0] len=3: 9051ff 94 | QQ.........: 51 95 | Data.......: None 96 | packet: COMPLETION for socket 01 97 | ----- 98 | packet (sent) [0 => 1] len=7: 8101043f0100ff 99 | QQ.........: 01 100 | (Command) 101 | RR.........: 04 102 | (Camera [1]) 103 | Data.......: 3f0100 104 | ----- 105 | packet (recv) [1 => 0] len=3: 9041ff 106 | QQ.........: 41 107 | Data.......: None 108 | packet: ACK for socket 01 109 | DEBUG: ABS POS TO 1440/360 110 | ----- 111 | packet (recv: ignored) [1 => 0] len=3: 9051ff 112 | QQ.........: 51 113 | Data.......: None 114 | packet: COMPLETION for socket 01 115 | ----- 116 | packet (sent) [0 => 1] len=15: 81010602141800050a0000010608ff 117 | QQ.........: 01 118 | (Command) 119 | RR.........: 06 120 | (Pan/Tilter) 121 | Data.......: 02141800050a0000010608 122 | ----- 123 | packet (recv) [1 => 0] len=3: 9041ff 124 | QQ.........: 41 125 | Data.......: None 126 | packet: ACK for socket 01 127 | DEBUG: cam_memory command 128 | ----- 129 | packet (recv: ignored) [1 => 0] len=3: 9051ff 130 | QQ.........: 51 131 | Data.......: None 132 | packet: COMPLETION for socket 01 133 | ----- 134 | packet (sent) [0 => 1] len=7: 8101043f0101ff 135 | QQ.........: 01 136 | (Command) 137 | RR.........: 04 138 | (Camera [1]) 139 | Data.......: 3f0101 140 | ----- 141 | packet (recv) [1 => 0] len=3: 9041ff 142 | QQ.........: 41 143 | Data.......: None 144 | packet: ACK for socket 01 145 | DEBUG: ABS POS TO 0/0 146 | ----- 147 | packet (recv: ignored) [1 => 0] len=3: 9051ff 148 | QQ.........: 51 149 | Data.......: None 150 | packet: COMPLETION for socket 01 151 | ----- 152 | packet (sent) [0 => 1] len=15: 8101060214180000000000000000ff 153 | QQ.........: 01 154 | (Command) 155 | RR.........: 06 156 | (Pan/Tilter) 157 | Data.......: 0214180000000000000000 158 | ----- 159 | packet (recv) [1 => 0] len=3: 9041ff 160 | QQ.........: 41 161 | Data.......: None 162 | packet: ACK for socket 01 163 | DEBUG: cam_memory command 164 | ----- 165 | packet (recv: ignored) [1 => 0] len=3: 9051ff 166 | QQ.........: 51 167 | Data.......: None 168 | packet: COMPLETION for socket 01 169 | ----- 170 | packet (sent) [0 => 1] len=7: 8101043f0102ff 171 | QQ.........: 01 172 | (Command) 173 | RR.........: 04 174 | (Camera [1]) 175 | Data.......: 3f0102 176 | ----- 177 | packet (recv) [1 => 0] len=3: 9041ff 178 | QQ.........: 41 179 | Data.......: None 180 | packet: ACK for socket 01 181 | DEBUG: cam_memory command 182 | ----- 183 | packet (recv: ignored) [1 => 0] len=3: 9051ff 184 | QQ.........: 51 185 | Data.......: None 186 | packet: COMPLETION for socket 01 187 | ----- 188 | packet (sent) [0 => 1] len=7: 8101043f0200ff 189 | QQ.........: 01 190 | (Command) 191 | RR.........: 04 192 | (Camera [1]) 193 | Data.......: 3f0200 194 | ----- 195 | packet (recv) [1 => 0] len=3: 9041ff 196 | QQ.........: 41 197 | Data.......: None 198 | packet: ACK for socket 01 199 | DEBUG: cam_memory command 200 | ----- 201 | packet (recv: ignored) [1 => 0] len=3: 9051ff 202 | QQ.........: 51 203 | Data.......: None 204 | packet: COMPLETION for socket 01 205 | ----- 206 | packet (sent) [0 => 1] len=7: 8101043f0201ff 207 | QQ.........: 01 208 | (Command) 209 | RR.........: 04 210 | (Camera [1]) 211 | Data.......: 3f0201 212 | ----- 213 | packet (recv) [1 => 0] len=3: 9041ff 214 | QQ.........: 41 215 | Data.......: None 216 | packet: ACK for socket 01 217 | DEBUG: cam_memory command 218 | ----- 219 | packet (recv: ignored) [1 => 0] len=3: 9051ff 220 | QQ.........: 51 221 | Data.......: None 222 | packet: COMPLETION for socket 01 223 | ----- 224 | packet (sent) [0 => 1] len=7: 8101043f0202ff 225 | QQ.........: 01 226 | (Command) 227 | RR.........: 04 228 | (Camera [1]) 229 | Data.......: 3f0202 230 | ----- 231 | packet (recv) [1 => 0] len=3: 9041ff 232 | QQ.........: 41 233 | Data.......: None 234 | packet: ACK for socket 01 235 | ----- 236 | packet (sent) [0 => 1] len=6: 8101040003ff 237 | QQ.........: 01 238 | (Command) 239 | RR.........: 04 240 | (Camera [1]) 241 | Data.......: 0003 242 | ----- 243 | packet (recv) [1 => 0] len=3: 9042ff 244 | QQ.........: 42 245 | Data.......: None 246 | packet: ACK for socket 02 247 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf8 -*- 3 | # 4 | # PyVisca - Implementation of the Visca serial protocol in python 5 | # Copyright (C) 2013 Florian Streibelt pyvisca@f-streibelt.de 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, version 2 only. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | """PyVisca by Florian Streibelt """ 22 | 23 | # 24 | # This is used for testing the functionality while developing, 25 | # expect spaghetti code... 26 | # 27 | 28 | def main(): 29 | 30 | from pyviscalib.visca import Visca 31 | from time import sleep 32 | 33 | v=Visca() 34 | 35 | v.cmd_adress_set() 36 | 37 | v.cmd_if_clear_all() 38 | 39 | CAM=1 40 | 41 | # v.cmd_cam_power_off(CAM) 42 | 43 | v.cmd_cam_power_on(CAM) 44 | 45 | v.cmd_cam_auto_power_off(CAM,2) 46 | 47 | v.cmd_datascreen_on(CAM) 48 | 49 | 50 | sleep(3) 51 | v.cmd_ptd_abs(CAM,pp=-1440,tp=-360) 52 | sleep(3) 53 | v.cmd_cam_memory_set(CAM,0) 54 | 55 | sleep(3) 56 | v.cmd_ptd_abs(CAM,pp=1440,tp=360) 57 | sleep(3) 58 | v.cmd_cam_memory_set(CAM,1) 59 | 60 | sleep(3) 61 | v.cmd_ptd_abs(CAM,pp=0,tp=0) 62 | sleep(3) 63 | v.cmd_cam_memory_set(CAM,2) 64 | 65 | sleep(5) 66 | v.cmd_cam_memory_recall(CAM,0) 67 | sleep(3) 68 | v.cmd_cam_memory_recall(CAM,1) 69 | sleep(3) 70 | v.cmd_cam_memory_recall(CAM,2) 71 | 72 | 73 | # sleep(1) 74 | # v.cmd_cam_zoom_tele(CAM) 75 | # sleep(2) 76 | # v.cmd_cam_zoom_stop(CAM) 77 | # sleep(3) 78 | # 79 | # v.cmd_cam_zoom_wide(CAM) 80 | # sleep(7) 81 | 82 | # v.cmd_cam_zoom_tele_speed(CAM,0) 83 | # sleep(7) 84 | # v.cmd_cam_zoom_wide_speed(CAM,0) 85 | # sleep(7) 86 | # v.cmd_cam_zoom_tele_speed(CAM,7) 87 | # sleep(7) 88 | # v.cmd_cam_zoom_wide_speed(CAM,7) 89 | # sleep(7) 90 | 91 | #maximum digital zoom: 92 | # v.cmd_cam_zoom_direct(CAM,0x7000) 93 | # sleep(7) 94 | #maximum optical zoom 95 | # v.cmd_cam_zoom_direct(CAM,0x4000) 96 | # sleep(7) 97 | #no zoom 98 | # v.cmd_cam_zoom_direct(CAM,0x0) 99 | 100 | # v.cmd_cam_dzoom_off(CAM) 101 | # v.cmd_cam_zoom_direct(CAM,0x7000) 102 | # sleep(7) 103 | # v.cmd_cam_wide_cinema(CAM) 104 | # sleep(7) 105 | # v.cmd_cam_wide_full(CAM) 106 | # sleep(7) 107 | # v.cmd_cam_wide_off(CAM) 108 | # sleep(7) 109 | 110 | # v.cmd_cam_lr_reverse_on(CAM) 111 | # sleep(2) 112 | # v.cmd_cam_lr_reverse_off(CAM) 113 | 114 | # v.cmd_cam_zoom_direct(CAM,0x7000) 115 | # sleep(3) 116 | # v.cmd_cam_freeze_on(CAM) 117 | # sleep(2) 118 | 119 | # v.cmd_cam_zoom_direct(CAM,0x0) 120 | # sleep(4) 121 | # v.cmd_cam_freeze_off(CAM) 122 | 123 | # v.cmd_cam_picture_effect_off(CAM) 124 | 125 | # for i in range(0,9): 126 | # v.cmd_cam_picture_effect(CAM,i) 127 | # sleep(3) 128 | 129 | # for i in range(0,5): 130 | # v.cmd_cam_digital_effect(CAM,i) 131 | # for level in range(0,0x21): 132 | # v.cmd_cam_digital_effect_level(CAM,level) 133 | # sleep(2) 134 | 135 | # v.cmd_ptd_up(CAM) 136 | # sleep(3) 137 | # v.cmd_ptd_down(CAM) 138 | # 139 | # sleep(3) 140 | # 141 | # v.cmd_ptd_up(CAM,2) 142 | # sleep(3) 143 | # v.cmd_ptd_down(CAM,2) 144 | # 145 | # 146 | # v.cmd_ptd_left(CAM) 147 | # sleep(3) 148 | # v.cmd_ptd_right(CAM,2) 149 | # sleep(3) 150 | # v.cmd_ptd_right(CAM) 151 | # sleep(1) 152 | # v.cmd_ptd_left(CAM) 153 | # sleep(1) 154 | # v.cmd_ptd_right(CAM) 155 | 156 | 157 | # v.cmd_ptd_upleft(CAM) 158 | # sleep(2) 159 | # 160 | # v.cmd_ptd_upright(CAM) 161 | # sleep(2) 162 | # 163 | # v.cmd_ptd_downleft(CAM) 164 | # sleep(2) 165 | # 166 | # v.cmd_ptd_downright(CAM) 167 | # sleep(2) 168 | # 169 | # v.cmd_ptd_home(CAM) 170 | # sleep(2) 171 | # v.cmd_ptd_reset(CAM) 172 | 173 | v.cmd_cam_power_off(CAM) 174 | 175 | if __name__ == '__main__': 176 | try: 177 | main() 178 | except KeyboardInterrupt: 179 | pass 180 | 181 | 182 | -------------------------------------------------------------------------------- /pyviscalib/__init__.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf8 -*- 3 | # 4 | # PyVisca - Implementation of the Visca serial protocol in python 5 | # Copyright (C) 2013 Florian Streibelt pyvisca@f-streibelt.de 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, version 2 only. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | """PyVisca by Florian Streibelt """ 22 | 23 | -------------------------------------------------------------------------------- /pyviscalib/visca.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf8 -*- 3 | # 4 | # PyVisca - Implementation of the Visca serial protocol in python 5 | # Copyright (C) 2013 Florian Streibelt pyvisca@f-streibelt.de 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, version 2 only. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 | # USA 20 | 21 | """PyVisca by Florian Streibelt """ 22 | 23 | import serial,sys 24 | from thread import allocate_lock 25 | 26 | class Visca(): 27 | 28 | def __init__(self,portname="/dev/ttyUSB0"): 29 | self.serialport=None 30 | self.mutex = allocate_lock() 31 | self.portname=portname 32 | self.open_port() 33 | 34 | def open_port(self): 35 | 36 | self.mutex.acquire() 37 | 38 | if (self.serialport == None): 39 | try: 40 | self.serialport = serial.Serial(self.portname,9600,timeout=2,stopbits=1,bytesize=8,rtscts=False, dsrdtr=False) 41 | self.serialport.flushInput() 42 | except Exception as e: 43 | print ("Exception opening serial port '%s' for display: %s\n" % (self.portname,e)) 44 | raise e 45 | self.serialport = None 46 | 47 | self.mutex.release() 48 | 49 | 50 | def dump(self,packet,title=None): 51 | if not packet or len(packet)==0: 52 | return 53 | 54 | header=ord(packet[0]) 55 | term=ord(packet[-1:]) 56 | qq=ord(packet[1]) 57 | 58 | sender = (header&0b01110000)>>4 59 | broadcast = (header&0b1000)>>3 60 | recipient = (header&0b0111) 61 | 62 | if broadcast: 63 | recipient_s="*" 64 | else: 65 | recipient_s=str(recipient) 66 | 67 | print "-----" 68 | 69 | if title: 70 | print "packet (%s) [%d => %s] len=%d: %s" % (title,sender,recipient_s,len(packet),packet.encode('hex')) 71 | else: 72 | print "packet [%d => %s] len=%d: %s" % (sender,sender,recipient_s,len(packet),packet.encode('hex')) 73 | 74 | print " QQ.........: %02x" % qq 75 | 76 | if qq==0x01: 77 | print " (Command)" 78 | if qq==0x09: 79 | print " (Inquiry)" 80 | 81 | if len(packet)>3: 82 | rr=ord(packet[2]) 83 | print " RR.........: %02x" % rr 84 | 85 | if rr==0x00: 86 | print " (Interface)" 87 | if rr==0x04: 88 | print " (Camera [1])" 89 | if rr==0x06: 90 | print " (Pan/Tilter)" 91 | 92 | if len(packet)>4: 93 | data=packet[3:-1] 94 | print " Data.......: %s" % data.encode('hex') 95 | else: 96 | print " Data.......: None" 97 | 98 | if not term==0xff: 99 | print "ERROR: Packet not terminated correctly" 100 | return 101 | 102 | if len(packet)==3 and ((qq & 0b11110000)>>4)==4: 103 | socketno = (qq & 0b1111) 104 | print " packet: ACK for socket %02x" % socketno 105 | 106 | if len(packet)==3 and ((qq & 0b11110000)>>4)==5: 107 | socketno = (qq & 0b1111) 108 | print " packet: COMPLETION for socket %02x" % socketno 109 | 110 | if len(packet)>3 and ((qq & 0b11110000)>>4)==5: 111 | socketno = (qq & 0b1111) 112 | ret=packet[2:-1].encode('hex') 113 | print " packet: COMPLETION for socket %02x, data=%s" % (socketno,ret) 114 | 115 | if len(packet)==4 and ((qq & 0b11110000)>>4)==6: 116 | print " packet: ERROR!" 117 | 118 | socketno = (qq & 0b00001111) 119 | errcode = ord(packet[2]) 120 | 121 | #these two are special, socket is zero and has no meaning: 122 | if errcode==0x02 and socketno==0: 123 | print " : Syntax Error" 124 | if errcode==0x03 and socketno==0: 125 | print " : Command Buffer Full" 126 | 127 | 128 | if errcode==0x04: 129 | print " : Socket %i: Command canceled" % socketno 130 | 131 | if errcode==0x05: 132 | print " : Socket %i: Invalid socket selected" % socketno 133 | 134 | if errcode==0x41: 135 | print " : Socket %i: Command not executable" % socketno 136 | 137 | if len(packet)==3 and qq==0x38: 138 | print "Network Change - we should immedeately issue a renumbering!" 139 | 140 | 141 | def recv_packet(self,extra_title=None): 142 | # read up to 16 bytes until 0xff 143 | packet='' 144 | count=0 145 | while count<16: 146 | s=self.serialport.read(1) 147 | if s: 148 | byte = ord(s) 149 | count+=1 150 | packet=packet+chr(byte) 151 | else: 152 | print "ERROR: Timeout waiting for reply" 153 | break 154 | if byte==0xff: 155 | break 156 | 157 | if extra_title: 158 | self.dump(packet,"recv: %s" % extra_title) 159 | else: 160 | self.dump(packet,"recv") 161 | return packet 162 | 163 | 164 | def _write_packet(self,packet): 165 | 166 | if not self.serialport.isOpen(): 167 | sys.exit(1) 168 | 169 | # lets see if a completion message or someting 170 | # else waits in the buffer. If yes dump it. 171 | if self.serialport.inWaiting(): 172 | self.recv_packet("ignored") 173 | 174 | self.serialport.write(packet) 175 | self.dump(packet,"sent") 176 | 177 | 178 | 179 | def send_packet(self,recipient,data): 180 | """ 181 | according to the documentation: 182 | 183 | |------packet (3-16 bytes)---------| 184 | 185 | header message terminator 186 | (1 byte) (1-14 bytes) (1 byte) 187 | 188 | | X | X . . . . . . . . . . X | X | 189 | 190 | header: terminator: 191 | 1 s2 s1 s0 0 r2 r1 r0 0xff 192 | 193 | with r,s = recipient, sender msb first 194 | 195 | for broadcast the header is 0x88! 196 | 197 | we use -1 as recipient to send a broadcast! 198 | 199 | """ 200 | 201 | # we are the controller with id=0 202 | sender = 0 203 | 204 | if recipient==-1: 205 | #broadcast: 206 | rbits=0x8 207 | else: 208 | # the recipient (address = 3 bits) 209 | rbits=recipient & 0b111 210 | 211 | sbits=(sender & 0b111)<<4 212 | 213 | header=0b10000000 | sbits | rbits 214 | 215 | terminator=0xff 216 | 217 | packet = chr(header)+data+chr(terminator) 218 | 219 | self.mutex.acquire() 220 | 221 | self._write_packet(packet) 222 | 223 | reply = self.recv_packet() 224 | 225 | 226 | if reply[-1:] != '\xff': 227 | print "received packet not terminated correctly: %s" % reply.encode('hex') 228 | reply=None 229 | 230 | self.mutex.release() 231 | 232 | return reply 233 | 234 | 235 | def send_broadcast(self,data): 236 | # shortcut 237 | return self.send_packet(-1,data) 238 | 239 | 240 | 241 | def i2v(self,value): 242 | """ 243 | return word as dword in visca format 244 | packets are not allowed to be 0xff 245 | so for numbers the first nibble is 0000 246 | and 0xfd gets encoded into 0x0f 0x0xd 247 | """ 248 | ms = (value & 0b1111111100000000) >> 8 249 | ls = (value & 0b0000000011111111) 250 | p=(ms&0b11110000)>>4 251 | r=(ls&0b11110000)>>4 252 | q=ms&0b1111 253 | s=ls&0b1111 254 | return chr(p)+chr(q)+chr(r)+chr(s) 255 | 256 | 257 | 258 | def cmd_adress_set(self): 259 | """ 260 | starts enumerating devices, sends the first adress to use on the bus 261 | reply is the same packet with the next free adress to use 262 | """ 263 | 264 | #address of first device. should be 1: 265 | first=1 266 | 267 | reply = self.send_broadcast('\x30'+chr(first)) # set address 268 | 269 | if not reply: 270 | print "No reply from the bus." 271 | sys.exit(1) 272 | 273 | if len(reply)!=4 or reply[-1:]!='\xff': 274 | print "ERROR enumerating devices" 275 | sys.exit(1) 276 | if reply[0] != '\x88': 277 | print "ERROR: expecting broadcast answer to an enumeration request" 278 | sys.exit(1) 279 | address = ord(reply[2]) 280 | 281 | d=address-first 282 | print "debug: found %i devices on the bus" % d 283 | 284 | if d==0: 285 | sys.exit(1) 286 | 287 | 288 | def cmd_if_clear_all(self): 289 | reply=self.send_broadcast( '\x01\x00\x01') # interface clear all 290 | if not reply[1:]=='\x01\x00\x01\xff': 291 | print "ERROR clearing all interfaces on the bus!" 292 | sys.exit(1) 293 | 294 | print "debug: all interfaces clear" 295 | 296 | 297 | def cmd_cam(self,device,subcmd): 298 | packet='\x01\x04'+subcmd 299 | reply = self.send_packet(device,packet) 300 | #FIXME: check returned data here and retransmit? 301 | 302 | return reply 303 | 304 | def cmd_pt(self,device,subcmd): 305 | packet='\x01\x06'+subcmd 306 | reply = self.send_packet(device,packet) 307 | #FIXME: check returned data here and retransmit? 308 | 309 | return reply 310 | 311 | 312 | 313 | 314 | 315 | # POWER control 316 | 317 | def cmd_cam_power(self,device,onoff): 318 | if onoff: 319 | pwr='\x00\x02' 320 | else: 321 | pwr='\x00\x03' 322 | return self.cmd_cam(device,pwr) 323 | 324 | def cmd_cam_power_on(self,device): 325 | return self.cmd_cam_power(device,True) 326 | 327 | def cmd_cam_power_off(self,device): 328 | return self.cmd_cam_power(device,False) 329 | 330 | 331 | def cmd_cam_auto_power_off(self,device,time=0): 332 | """ 333 | time = minutes without command until standby 334 | 0: disable 335 | 0xffff: 65535 minutes 336 | """ 337 | subcmd='\x40'+self.i2v(time) 338 | 339 | return self.cmd_cam(device,subcmd) 340 | 341 | 342 | # ZOOM control 343 | 344 | def cmd_cam_zoom_stop(self,device): 345 | subcmd="\x07\x00" 346 | return self.cmd_cam(device,subcmd) 347 | 348 | def cmd_cam_zoom_tele(self,device): 349 | subcmd="\x07\x02" 350 | return self.cmd_cam(device,subcmd) 351 | 352 | def cmd_cam_zoom_wide(self,device): 353 | subcmd="\x07\x03" 354 | return self.cmd_cam(device,subcmd) 355 | 356 | 357 | def cmd_cam_zoom_tele_speed(self,device,speed): 358 | """ 359 | zoom in with speed = 0..7 360 | """ 361 | sbyte=0x20+(speed&0b111) 362 | subcmd="\x07"+chr(sbyte) 363 | return self.cmd_cam(device,subcmd) 364 | 365 | def cmd_cam_zoom_wide_speed(self,device,speed): 366 | """ 367 | zoom in with speed = 0..7 368 | """ 369 | sbyte=0x30+(speed&0b111) 370 | subcmd="\x07"+chr(sbyte) 371 | return self.cmd_cam(device,subcmd) 372 | 373 | def cmd_cam_zoom_direct(self,device,zoom): 374 | """ 375 | zoom to value 376 | optical: 0..4000 377 | digital: 4000..7000 (1x - 4x) 378 | """ 379 | subcmd="\x47"+self.i2v(zoom) 380 | return self.cmd_cam(device,subcmd) 381 | 382 | #Digital Zoom control on/off 383 | def cmd_cam_dzoom(self,device,state): 384 | if state: 385 | subcmd="\x06\x02" 386 | else: 387 | subcmd="\x06\x03" 388 | 389 | return self.cmd_cam(device,subcmd) 390 | 391 | def cmd_cam_dzoom_on(self,device): 392 | return self.cmd_cam_dzoom(device,True) 393 | 394 | def cmd_cam_dzoom_off(self,device): 395 | return self.cmd_cam_dzoom(device,False) 396 | 397 | 398 | 399 | #FIXME: CAM_FOCUS COMMANDS 400 | #FIXME: CAM_WB 401 | #FIXME: CAM_?GAIN 402 | #FIXME: CAM_AE 403 | #FIXME: CAM_SlowShutter 404 | #FIXME: CAM_Shutter 405 | #FIXME: CAM_Iris 406 | #FIXME: CAM_Gain 407 | #FIXME: CAM_Bright 408 | #FIXME: CAM_ExpComp 409 | #FIXME: CAM_BackLight 410 | #FIXME: CAM_Aperature 411 | 412 | # 16:9 / Wide format: 413 | def cmd_cam_wide(self,device,mode): 414 | subcmd="\x60"+chr(mode) 415 | return self.cmd_cam(device,subcmd) 416 | 417 | def cmd_cam_wide_off(self,device): 418 | return self.cmd_cam_wide(device,0x00) 419 | 420 | def cmd_cam_wide_cinema(self,device): 421 | return self.cmd_cam_wide(device,0x01) 422 | 423 | def cmd_cam_wide_full(self,device): 424 | return self.cmd_cam_wide(device,0x02) 425 | 426 | 427 | # mirror 428 | def cmd_cam_lr_reverse(self,device,mode): 429 | subcmd="\x61"+chr(mode) 430 | return self.cmd_cam(device,subcmd) 431 | 432 | def cmd_cam_lr_reverse_on(self,device): 433 | return self.cmd_cam_lr_reverse(device,0x02) 434 | 435 | def cmd_cam_lr_reverse_off(self,device): 436 | return self.cmd_cam_lr_reverse(device,0x03) 437 | 438 | # freeze 439 | def cmd_cam_freeze(self,device,mode): 440 | subcmd="\x62"+chr(mode) 441 | return self.cmd_cam(device,subcmd) 442 | 443 | def cmd_cam_freeze_on(self,device): 444 | return self.cmd_cam_freeze(device,0x02) 445 | 446 | def cmd_cam_freeze_off(self,device): 447 | return self.cmd_cam_freeze(device,0x03) 448 | 449 | 450 | 451 | # Picture Effects 452 | def cmd_cam_picture_effect(self,device,mode): 453 | subcmd="\x63"+chr(mode) 454 | return self.cmd_cam(device,subcmd) 455 | 456 | def cmd_cam_picture_effect_off(self,device): 457 | return self.cmd_cam_picture_effect(device,0x00) 458 | 459 | def cmd_cam_picture_effect_pastel(self,device): 460 | return self.cmd_cam_picture_effect(device,0x01) 461 | 462 | def cmd_cam_picture_effect_negart(self,device): 463 | return self.cmd_cam_picture_effect(device,0x02) 464 | 465 | def cmd_cam_picture_effect_sepa(self,device): 466 | return self.cmd_cam_picture_effect(device,0x03) 467 | 468 | def cmd_cam_picture_effect_bw(self,device): 469 | return self.cmd_cam_picture_effect(device,0x04) 470 | 471 | def cmd_cam_picture_effect_solarize(self,device): 472 | return self.cmd_cam_picture_effect(device,0x05) 473 | 474 | def cmd_cam_picture_effect_mosaic(self,device): 475 | return self.cmd_cam_picture_effect(device,0x06) 476 | 477 | def cmd_cam_picture_effect_slim(self,device): 478 | return self.cmd_cam_picture_effect(device,0x07) 479 | 480 | def cmd_cam_picture_effect_stretch(self,device): 481 | return self.cmd_cam_picture_effect(device,0x08) 482 | 483 | 484 | 485 | # Digital Effect 486 | 487 | def cmd_cam_digital_effect(self,device,mode): 488 | subcmd="\x64"+chr(mode) 489 | return self.cmd_cam(device,subcmd) 490 | 491 | def cmd_cam_digital_effect_off(self,device): 492 | return self.cmd_cam_digital_effect(device,0x00) 493 | 494 | def cmd_cam_digital_effect_still(self,device): 495 | return self.cmd_cam_digital_effect(device,0x01) 496 | 497 | def cmd_cam_digital_effect_flash(self,device): 498 | return self.cmd_cam_digital_effect(device,0x02) 499 | 500 | def cmd_cam_digital_effect_lumi(self,device): 501 | return self.cmd_cam_digital_effect(device,0x03) 502 | 503 | def cmd_cam_digital_effect_trail(self,device): 504 | return self.cmd_cam_digital_effect(device,0x04) 505 | 506 | 507 | def cmd_cam_digital_effect_level(self,device,level): 508 | subcmd="\x65"+chr( 0b00111111 & level) 509 | return self.cmd_cam(device,subcmd) 510 | 511 | 512 | # memory of settings including position 513 | def cmd_cam_memory(self,device,func,num): 514 | if num>5: 515 | num=5 516 | if func<0 or func>2: 517 | return 518 | print "DEBUG: cam_memory command" 519 | subcmd="\x3f"+chr(func)+chr( 0b0111 & num) 520 | return self.cmd_cam(device,subcmd) 521 | 522 | 523 | #FIXME; Can only be executed when motion has stopped!!! 524 | def cmd_cam_memory_reset(self,device,num): 525 | return self.cmd_cam_memory(device,0x00,num) 526 | 527 | def cmd_cam_memory_set(self,device,num): 528 | return self.cmd_cam_memory(device,0x01,num) 529 | 530 | def cmd_cam_memory_recall(self,device,num): 531 | return self.cmd_cam_memory(device,0x02,num) 532 | 533 | 534 | # Datascreen control 535 | 536 | def cmd_datascreen(self,device,func): 537 | subcmd='\x06'+chr(func) 538 | return self.cmd_pt(device,subcmd) 539 | 540 | def cmd_datascreen_on(self,device): 541 | return self.cmd_datascreen(device,0x02) 542 | 543 | def cmd_datascreen_off(self,device): 544 | return self.cmd_datascreen(device,0x03) 545 | 546 | def cmd_datascreen_toggle(self,device): 547 | return self.cmd_datascreen(device,0x10) 548 | 549 | 550 | #FIXME: IR_Receive 551 | #FIXME: IR_Receive_Return 552 | 553 | 554 | # Pan and Tilt Drive: 555 | 556 | def cmd_ptd(self,device,ps,ts,lr,ud): 557 | 558 | subcmd='\x01'+chr(ps)+chr(ts)+chr(lr)+chr(ud) 559 | return self.cmd_pt(device,subcmd) 560 | 561 | def cmd_ptd_up(self,device,ts=0x14): 562 | return self.cmd_ptd(device,0,ts,0x03,0x01) 563 | 564 | def cmd_ptd_down(self,device,ts=0x14): 565 | return self.cmd_ptd(device,0,ts,0x03,0x02) 566 | 567 | def cmd_ptd_left(self,device,ps=0x18): 568 | return self.cmd_ptd(device,ps,0,0x01,0x03) 569 | 570 | def cmd_ptd_right(self,device,ps=0x18): 571 | return self.cmd_ptd(device,ps,0,0x02,0x03) 572 | 573 | 574 | def cmd_ptd_upleft(self,device,ts=0x14,ps=0x18): 575 | return self.cmd_ptd(device,ps,ts,0x01,0x01) 576 | 577 | def cmd_ptd_upright(self,device,ts=0x14,ps=0x18): 578 | return self.cmd_ptd(device,ps,ts,0x02,0x01) 579 | 580 | def cmd_ptd_downleft(self,device,ts=0x14,ps=0x18): 581 | return self.cmd_ptd(device,ps,ts,0x01,0x02) 582 | 583 | def cmd_ptd_downright(self,device,ts=0x14,ps=0x18): 584 | return self.cmd_ptd(device,ps,ts,0x02,0x02) 585 | 586 | def cmd_ptd_stop(self,device): 587 | return self.cmd_ptd(device,0,0,0x03,0x03) 588 | 589 | 590 | 591 | def cmd_ptd_abs(self,device,ts=0x14,ps=0x18,pp=0,tp=0): 592 | 593 | print "DEBUG: ABS POS TO %d/%d" % (pp,tp) 594 | 595 | # pp: range: -1440 - 1440 596 | if pp<0: 597 | p=(((pp*-1)-1)^0xffff) 598 | else: 599 | p=pp 600 | 601 | #tp: range -360 - 360 602 | if tp<0: 603 | t=(((tp*-1)-1)^0xffff) 604 | else: 605 | t=tp 606 | 607 | subcmd='\x02'+chr(ts)+chr(ps)+self.i2v(p)+self.i2v(t) 608 | return self.cmd_pt(device,subcmd) 609 | 610 | 611 | def cmd_ptd_home(self,device): 612 | subcmd='\x04' 613 | return self.cmd_pt(device,subcmd) 614 | 615 | def cmd_ptd_reset(self,device): 616 | subcmd='\x05' 617 | return self.cmd_pt(device,subcmd) 618 | 619 | 620 | #FIXME: Pan-tiltLimitSet 621 | 622 | 623 | 624 | 625 | --------------------------------------------------------------------------------