вторник, 10 декабря 2024 г.

AI coder: mouse clicker

Continuing the series of articles on using ChatGPT as a software developer. In this article, I will show you how to ask ChatGPT to create a script that performs a click at a specific position via the mouse using a hotkey. Here is the initial version of the chat where I ask what I can use to do it, and in the subsequent chat, I finalize the script (copy the latest version of the script by clicking "copy code" in the upper right corner of the script window in the chat, and paste it into a new text file, naming it, for example, "2clicks.ahk"). They are in Russian, but you can ask Google Chrome to translate them into your language.

Now, you can run the script by double-clicking it if you have installed the AutoHotKey v2 tool. You can assign positions to click using "Alt-F5" and "Alt-F6", and click on them afterward using "F5" and "F6", respectively. You can change the hotkeys in the script, adjust their numbers, etc. To stop the script, unload it via the "H" icon in the tray area or use "Suspend Hotkeys" to temporarily disable the hotkeys.

Do you want help using ChatGPT? Drop me a message at virtualvat@gmail.com!

понедельник, 9 декабря 2024 г.

AI coder: project DocPic

Starting a series of articles about ChatGPT use for software developers. Even if you are not a software developer, you can still easily create code for your needs using such a powerful modern tool as AI! I prefer to use ChatGPT, but nowadays there are several approaches that allow you to do the same—just choose the one that suits you. For my first example, I'd like to demonstrate how to extract a picture for documents using face detection in a photo. The script is written in Python—install it on your computer and run the script, which you can copy from this chat with ChatGPT: Project DocPic. Explore the chat to see how easy it is to do the same yourself, even without any knowledge of programming! It's in Russian, but you can ask Google Chrome to translate it into your language.

To create the script, create a new text file, copy the latest version from the chat (click "copy code" in the upper right corner of the script window), and name it, for example, DocPic.py.

Now, just take a photo of a person and pass it as a parameter to the script along with the required proportions for the photo, e.g.:

python DocPic.py <image_path> <aspect_width> <aspect_height>

For example, to make a photo for documents with a 3x4 aspect ratio, use:

python DocPic.py mypic.png 3 4

If you see any errors indicating that a specific module isn't found, you can install it via the command line using PIP, e.g.:

pip install dlib

It's better to use a command line started as an administrator (press Win+R, type "cmd", and press CTRL+SHIFT+Enter) to install any missing modules.

If you see any other errors, just ask ChatGPT how to resolve them :)

Here is an example of the source picture:


And here is how the script transforms it:

Do you want help using ChatGPT? Drop me a message at virtualvat@gmail.com!

вторник, 7 мая 2024 г.

Streaming: why TCP not UDP

 If you are a skilled developer and have eaten a lot with development related to internet services you might be aware of the TCP vs UDP specifics and know more than very well that for such services like video streaming it's more natively to use UDP not TCP https://www.wowza.com/blog/udp-vs-tcp but why, say, YouTube and Netflix use TCP?

Because each problem should be started to be viewed from the business perspective and not technical. Let's review pros which UDP has against TCP for streaming:

1. Much higher speed
2. Will not be broken if something is lost in the middle
3. Can be broadcasted - e.g. 1 source can be received by many destinations

And cons:

1. Doesn't give guarantee that all packets will be received
2. The sequence of the packets can be disordered

TCP:

1. Is much slower but gives the 100% guarantee of the data integrity - the sequence of the packets will be correct and nothing will be lost.
2. Due to requirement for integrity the channel can be broken and require reestablishing. In the case of enough wide internet connection this can be easily compensated with caching.
2. Other benefits like ability to work via secure channels, etc...

Also we should take into respect the following factors:

1. Price delta for the internet connection with the increased speed is very low nowadays. e.g. Fizz asks $44 for 200 megabits and $45 for 400.
2. To receive quality video Full HD video we need around 10 megabits, for 4K - 40.
3. Most popular video services are "on demand" which means user picks e.g. a movie he want to see now, not a general TV channel with online translation which makes UDP broadcasting ability useless here.
4. To use UDP service providers must have their own software (like "Zoom" client) or aim hardware (e.g. TV set). HTTP2 standard ("just in Web Browser") covers TCP only.
5. From business perspective most services would like to cover as many clients as possible and most people prefer to have an ability to just open the web page to access its favorite video service instead of installing an additional software.
6. And of course all providers would like to save the money - once they have a solution via TCP to cover WEB approach, it's cheaper to re-use it e.g. in their software for TV. Development for UDP will be more expensive - you need to take a control of packets sequence by yourself and decide what to do with lost packets, how much to wait for them to decide that this part of the picture should be left broken, develop the workaround for the broken parts of the image (i.e. insert a "glitch"), etc. To maintain TCP you need only caching for probable slowdown in the channel or even break to just restore the channel.
7. Do people want to have even rarely broken picture while watching their lovely movie? If they can easily pay $1 extra for the double speed? Which can be used to transfer 8 4K simultaneous quality video via the TCP channel?
6+7. Even if providers decide to cover UDP as well they will need to increase their prices. So even if they have a brilliant solution not to affect the quality so much (I doubt) and propose to customers "we deliver you better picture within your 30 MBt channel so you can save not paying for 100 MBt channel"... Who would take this offer??

So dear DonQuixotes, with a big respect to your knowledge and technical background where you are definitely right :) TCP usually still wins there where you expect UDP should win. Just because of business :)

вторник, 26 сентября 2023 г.

GTP 4 without of GPT Plus subscription

Do you know that not only GPT Plus users may access the Open AI's GPT 4 model? If you want to try the upper level than GPT 3.5 and you are not ready to pay 20$ a month to access the GPT 4 it's possible to do this with help of any client working via the GPT API such as GPT4All. You need to register your account on OpenAI and define an API Key to access it. This key you will need to install the GPT 4 model in the GPT4All client.
Now if you try to access the chat it will return you error saying that GPT 4 access is available for pre-paid users only and provide this link https://help.openai.com/en/articles/7102672-how-can-i-access-gpt-4 to review what's necessary for this. And WOW... it is no need to have Plus accounnt for this :) But you need to charge your account for at least either 0.50$ or 1$ depending on when you had created your OpenAI account but switching to the billing page it will want you to put minimum 5$ :) But taking into consideration that per the pricing GPT content costs just 0.03$ for the input and 0.06$ per 1k tokens for the output it still can be much less than 20$ per month if you don't use it too much. For example around 5 experiments which outputted code samples (not so small ones) costed to me around 0.09$, you can watch for your billing history and usage in the cabinet. So now at least you may decide by yourself when it worth switching to 20$/month subscription.

суббота, 28 августа 2021 г.

Мальчик с феноменальной памятью

Team lead'ам о "мальчике с феноменальной памятью" (кто помнит этот анекдот, посмейтесь), занимающимися подбором персонала на работу - осторожно, крутой развод! Прочим будет весьма забавно прочитать сей пост, не пожалеете 🙂 Получил урок на собственном опыте. Навеяло написать после разговора с нашим HR которая давече уговаривала меня рассмотреть кандидатуру, который напрочь отказывался от live coding (кто не в теме - просьба продемонстрировать способность программировать вживую для решения заданных задач) на интервью. Довелось столкнуться с кандидатом, который теоретически просто "отстреливал" всё что у него не спросишь с весьма убедительной манерой общения. Немного насторожило то, что он сидел по стойке... т.е. сидке "смирно" (рассказывал что служил долго, но дело не в этом), и (особенно) на вопрос о том, насколько он готов заниматься (если что) вопросами, которые "чуть в стороне" от девелопмента (кто в теме, поймут насколько это бывает "больно" разработчикам, что может их отпугнуть), а именно (например) "потестировать перед релизом если тестировщики не успевают" или подобное, кандидат "отрапортовал" что "ну, я человек подневольный, что скажут, то и буду делать"... у меня в мозгах чуть "подвисло"... опять таки, кто в теме, сразу почуют неладное - ни один программист такое не скажет, ну не свойственно совершенно это нашему брату, тем более на рынке, где пять мест на одного толкового кандидата... Но ладно, я "схавал", может особенный человек, может много лет армии таки мозги подмыла, такое... Так вот, кроме того, что он "оттараторивал" любые теоретические вопросы, у него (!!!) был канал на youtube где он рассматривал сложные задачи по программированию (а-ля LeetCode и подобные) - в общем фарш по полной, на скрининге вы подумаете "ох нифигасе какой крутой кандидат мне попался, надо брать по-любому". А вот теперь самое интересное - когда мы дошли до live coding он оказывается... оперный театр... ЛЫКА НЕ ВЯЖЕТ! Пытался присобачить (не могу сказать по-другому) некий "крутой" алгоритм сортировки где-то из того же литкода (сказав о нём теоретически только) туда где он вообще ни к селу ни к городу... Оправдывается "я сегодня не спал, проблемы были", "на вашем сайте контраст плохой, я не вижу ничего", "да у меня тут знаете сколько мониторов, я теряюсь что шарить...", "да вы гляньте мой ютюб канал, я там и не такое лабаю", и т.д. Ну мы предложили организовать вторую сессию интервью, что бы он перед ней точно выспался, на которую он вначале согласился, а позже отменил...... Вот такое бывает, ребята 🙂 Походу человек с отличной памятью и контактами в IT сфере узнал что нужно теоретически для прохождения интервью, вызубрил вообще всё назубок, нашёл решения крутых задач, скопировал в свой канал на YouTube с очень умным лицом (и стойкой, т.е. сидкой "смирно") и задурманивает айтишные конторы... А ведь существую такие, и много, некоторые даже рекламируют (для привлечения) то, что интервью у них без лайв кодинга - так можно шикарно попасть на такого разводчика... учитывая то, что процедура on-boarding (ввода в курс дела, когда от кандидата ничего не требуется, кроме усвоения информации о разработке и разрабатываемом продукте по началу) длится до месяца, потом месяц-два когда можно постепенно допетрить что ... король-то голый... плюс время, за которое по контракту нужно предупредить человека об увольнении... разводчик может на ровном месте поднять 10-15 а то и больше штук баксов ))) и вперёд дальше по интервью, а айтишных контор-то на наш час доуя... А кстати можно и намного больше поднимать, понимая, что ты ничего на самом деле не сделаешь всё равно, продолжать собеседоваться не останавливаясь, запараллеливая процесс., устраиваясь в несколько контор одновременно, а ещё и фриланс подключить... Вот такое дело, ребятки 🙂 Так что дорогие кандидаты, которые действительно отказываются от лайв кодинга по причине проблемы "стойки за спиной", из-за чего многие впадают в ступор (в чём частично кстати и моя проблема) - простите и поймите, но я без лайв кодинга отныне "зась", предупреждайте о вашей проблеме, я пойму и буду делать большую на это скидку, но я обязан увидеть от кандидата "поток его мыслей" в процессе программирования, никак по-другому.

понедельник, 30 ноября 2020 г.

WSDL optimization tool

Some WSDLs are huge but are necessary to use for testing. For example SforceService.wsdl is huge and takes almost a minute to load in some tools and also it will cause unnecessaary delays on each call in runtime (e.g. I needed to wait about 10-15 minutes to complete a test which had many service calls in the application I develop). Here is the wsdl-optim WSDL optimization tool written on Java allowing to cut out everything else besides particular operations used including all related definitions. Also it can be used to cut off forgotten unused in any operation definitions. Known issues: when actual type can be successor of some other type (contains "base" attribute link to the parent) it can be cut by the tool as it cuts out all unreferenced directly types thus all childs too if there is no explicit link to them

пятница, 24 мая 2019 г.

Map value lazy initialization

Tired of the following pattern?


value = map.get(key);
if (value == null) {
    // Map value lazy initialization in act
    value = /* Init value */;
    map.put(key, value);
}
// Use value
Java2html


Here is the elegant solution from the Java 8:


import java.util.HashMap;
import java.util.Map;

public class MapInit {

  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    String ret;
    // Lambda function is called here as there is no value with "theKey" in the map
    // The same newly added value returned by the lambda function is returned 
    ret = map.computeIfAbsent("theKey", key -> "theValue");
    System.out.println(ret);
    System.out.println(map);
    // Lambda function isn't called here as there is the value with "theKey" in the map
    // Instead, the value with "theKey" is acquired from the map and returned
    ret = map.computeIfAbsent("theKey", key -> "theValue");
    System.out.println(ret);
    System.out.println(map);
    // The "mapping function" is called here as there is no value with "theInitiatedKey" in the map
    // The same newly allocated by the mapping function value is returned 
    ret = map.computeIfAbsent("theInitiatedKey", MapInit::valueInitiator);
    System.out.println(ret);
    System.out.println(map);
    // The "mapping function" isn't called here as there is the value with "theInitiatedKey" in the map
    // Instead, the value with "theInitiatedKey" is acquired from the map and returned
    ret = map.computeIfAbsent("theInitiatedKey", MapInit::valueInitiator);
    System.out.println(ret);
    System.out.println(map);
  }
  
  private static String valueInitiator(String key) {
    // The function is called if only the value with this key is absent from the map
    System.out.println("Initiating 'theInitiatedValue'");
    return "theInitiatedValue";
  }
}
Java2html

The output:

theValue
{theKey=theValue}
theValue
{theKey=theValue}
Initiating 'theInitiatedValue'
theInitiatedValue
{theKey=theValue, theInitiatedKey=theInitiatedValue}
theInitiatedValue
{theKey=theValue, theInitiatedKey=theInitiatedValue}


Inspired by the StackOverflow's question Java map.get(key) - automatically do put(key) and return if key doesn't exist?. Thanks for the solution to Roger Lindsjö.

вторник, 12 марта 2019 г.

HTTP replay tool

I searched through the internet but was not able to find anything around this and it was strange to me. I had an idea to resend full HTTP requests captured by e.g. Fiddler, TcpMon or even designed manually to the same or other host:port destination which is suitable e.g. running configured tasks on Jenkins, provide research to your code deployed on an Java Server such as Tomcat or JBoss, etc...

So I've created such tool and it is a part of the Simple Scheduler - you can download its binary and use couple of jars for this purpose, check the httpReplay.bat for instructions. The HTTP Replay tool description on the original site.
Beside simple single request the tool is able to perform batch simultaneous requests for e.g. load or DoS attack steadiness tests.

среда, 7 ноября 2018 г.

Restoring project's sources from Google Code

Thanks to the article How to recover a Google Code SVN Project and migrate to Github I found the way to download the SVN repository dump of my project J-Sche and was able to get the sources from there. Here are steps how I did it on Windows:

1. Download the SVN dump of the necessary project from the Google Code archive specifying the name of the project as red text in this link: https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/j-sche/repo.svndump.gz - just put this link into web browser address bar, click "enter" and the "repo.svndump.gz" dump file should be downloaded.
2. Un-gzip the file using any convenient application. I used Far Manager for this - locate desired location where to put decompressed file in one panel, locate the in the "repo.svndump.gz" in the opposite panel, click "ctrl + page down" to enter the archive, click F5 to copy the only "repo.svndump" file in it to the opposite panel's location - this is the easiest way to decompress it from the archive to the specified location.
3. Install Visual SVN Server, run it, add a user via right click on "Users", specifying "Create User...".
4. Right-click on "Repositories", select "Import Existing Repository", specify "Load repository from a dump file" and point the decompressed "repo.svndump", give a name to this repository. Now it should be appeared under the "Repositories". Open it, right click on the repository you've just created, specify "Copy URL to Clipboard".
5. Install the Tortoise SVN, go to a location you'd like to download project sources to using Explorer, right click here and choose "SVN Checkout". Tortoise' "Checkout" window should appear and the link, copied in the step 4 should appear in "URL of repository" automatically. Just click "OK" and the project sources from the repository content should be downloaded here.

понедельник, 11 сентября 2017 г.

Simple scheduler on Java

Let me introduce my project

The scheduler running as Windows Service isn't built on Quartz, with it's own easy-ro-read simple user-friendly configuration.

воскресенье, 20 апреля 2014 г.

Building Windows Service on Java using Apache Commons Daemon


I've came up with a pretty nice solution to realize the Windows Service using Java with help of Apache Commons Daemon. procrun.exe is used in Windows for that approach. It appears this approach is the potential candadate for the best practice so I want to share it with you. And of course I would like you to judge it - please welcome to comment!

ACD allows to use several methoods to execute the java application. For example you can use StartParams and StopParams along with StartClass and StopClass to use one method to start and stop the application - in this case you need to parse the corresponding parameter in the start/stop class to handle the corresponding action. You also can use different methods to execute the application specifying the StartMode and StopMode ... I prefer to use JVM method specifying different methods to start and stop the application.
To implement this I use StartMethod and StopMethod along with StartClass and StopClass to start and stop my service.

To examine and run following examples you need to download the sources from here or exporing the complete project JSche Simple Scheduler.

First, to learn the basics let's consider simplified example. To test it extract the archieve, build the maven project (I used maven 3 to assemble it) with "mvn package" command. Copy the resulted JavaWindowsServiceUsingCommonsDaemon-0.0.1-SNAPSHOT.jar to the simpleExample folder. Copy corresponding prunsrvXX.exe from the "bin" folder to the simpleExample too. Run the install_service.bat, check "Services". You should see new "Test Service" here. "logs" folder with couple of files iin it should be created. Now start the service in "Services". Check the console.log - you should detect logs messages dynamically added here.

Here is the RandomLoggerService.java class file to work as the service:

package test.service;


import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;


/*
 * A Modified version of Commons Daemon provided sample ProcrunService
 * The original can be found here
 * http://svn.apache.org/viewvc/commons/proper/daemon/trunk/src/samples/ProcrunService.java?view=markup
 */

/*

 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/**
 * Sample service implementation for use with Windows Procrun.
 <p>
 * Use the main() method for running as a Java application. Use the
 * start() and stop() methods for running as a jvm (in-process) service
 */
public class RandomLoggerService implements Runnable {

  /** The Constant MS_PER_SEC. */
  private static final long MS_PER_SEC = 1000L// Milliseconds in a second

  /** The logger thread. */
  private static Thread loggerThread; // start and stop are called
                          // from different threads
  /** The Constant random. */
  private static final Random random = new Random();

  private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");

  private static void log(String message) {
    System.out.println(df.format(new Date()) + message);
  }

  /**
   * This method simulates performing the work of the service. In this case, it just logs
   * a message any time between 1-5 seconds.
   * A real logging application would get its log messages from a queue or socket etc.
   */
  public void run() {
    log("Thread started");
    
    while (true) {
      long sleepTime = random.nextInt(41;
      
      try {
        log("pausing " + sleepTime + " seconds");
        Thread.sleep(sleepTime * MS_PER_SEC);
      catch (InterruptedException e) {
        log("Exiting");
        break;
      }
    }
  }

  /**
   * Start thread.
   
   */
  private static void startThread() {
    log("Starting the thread");
    loggerThread = new Thread(new RandomLoggerService());
    loggerThread.start();
  }

  /**
   * Start the jvm version of the service, and waits for it to complete.
   
   @param args
   *            ignored
   */
  public static void start(String[] args) {
    startThread();
    synchronized (loggerThread) {
      try {
        loggerThread.wait();
      catch (InterruptedException e) {
        log("'Wait' interrupted: " + e.getMessage());
      }
    }
  }

  /**
   * Stop the JVM version of the service.
   
   @param args
   *            ignored
   */
  public static void stop(String[] args) {
    if (loggerThread != null) {
      log("Stopping the thread");
      loggerThread.interrupt();
      synchronized (loggerThread) {
        loggerThread.notify();
      }
    else {
      log("No thread to interrupt");
    }
  }

  public static void main(String[] args) {
    // This method isn't used by the Apache Commons Daemon runner, it is defined to have a possibility
    // to emulate running the same as simple java application e.g. for the debug purpose
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        RandomLoggerService.stop(new String[] {});
      }
    });
    start(args);
  }
}
Java2html

2 methods are used here by Apache Daemon helper - "start" to start the service and "stop" to stop it. "main" function is given here to use the same class as java main class to have a possibility to run the same what Apache Daemon is doing for the class while it's being run as the service but in the console - to run it as a simple java application mode just run this class in the console.

The install_service.bat batch file to install the service:
rem Note you need to have JAVA_HOME to be set and point to the existed JDK

rem treat this folder as Application Home folder
set APP_HOME=%~dp0
rem remove last "\" from the path to Application Home
for %%F in ("%APP_HOME%") do set APP_HOME=%%~fF

set APP_JAR=%APP_HOME%\JavaWindowsServiceUsingCommonsDaemon-0.0.1-SNAPSHOT.jar
set START_CLASS=test.service.RandomLoggerService
set STOP_CLASS=%START_CLASS%
set START_METHOD=start
set STOP_METHOD=stop
set APP_LOGS_FOLDER=%APP_HOME%\logs
set APP_CONSOLE_LOG=%APP_LOGS_FOLDER%\console.log

if not exist "%APP_LOGS_FOLDER%" md "%APP_LOGS_FOLDER%"

prunsrv.exe //IS//TestService --DisplayName "Test Service" --Description "My Test Service" --LogPath "%APP_LOGS_FOLDER%"^
 --Install "%APP_HOME%\prunsrv.exe" --Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll" --StartPath "%APP_HOME%" --StopPath "%APP_HOME%"^
 --Classpath "%APP_JAR%" --StartClass %START_CLASS% --StopClass %STOP_CLASS% --StartMethod %START_METHOD% --StopMethod %STOP_METHOD%^
 --StartMode jvm --StopMode jvm --StdOutput "%APP_CONSOLE_LOG%" --StdError "%APP_CONSOLE_LOG%"

Here is close to minimum set of settings in this batch file. As I've said previously "method" specification is used to setup the access to Service handler. So "start" method is used to start the service, per Daemon documentation it must not exit until the seervice should run. "stop" method is to stop the service. To uninstall the service use the uninstall_service.bat.

Now let's switch to the most interesting set of batch files in "bin" folder - copy the same prunmgr.exe and JavaWindowsServiceUsingCommonsDaemon-0.0.1-SNAPSHOT.jar to that folder. Install the service using the similar batch file. It installs the service and configures it using the update_config.bat call. This file is intended to update the service configuration any time you need to change it. Just edit the update_config.bat and run it once. After that you need to (re)start the service for settings to take effect. Settings are stored in the registry. So next time when you are starting the service again they are retaken from there. E.g. you can uncomment the string setting the remote debugging ("-Xdebug" etc.) and after you restart the service you can access it to perform the remote debugging.
You can also use config_manager.bat to execute the UI tool allowing to edit the service settings in the dialog box. To apply these changes you also need to restart the service for settings to take effect. Note that if you run update_config.bat again after it will reset all parameters to the state kept in this batch file.
run_in_console.bat allows to run your service application in the console mode. You may find necessary to stop the same service to avoid conflicts between two simultaneous processes of the same application.
It's necessary to rename the procrun.exe for your particular application so in the "tasks list" you can see the appropriate executable name corresponding to your application name e.g. if it is necessary to "kill" the process.
Note that update_config.bat file contains some example options that are not needed by this class actually. These options should be removed in your application and replaced with any ones that are necessary for it. For instance proxy options are not necessary for this particular example.

Good luck :)

пятница, 16 августа 2013 г.

Command line in Far to new ConEmu console

Using [Far 2 + ConEmu]? Here is the solution how to run new command in Far Manager 2 targeting the new ConEmu console.
Download and run this file to add macros for Far into the registry.
Now use ALT+SHIFT clicking ENTER on any item you wish to run in the new ConEmu console of the same ConEmu which runs Far. If command line is empty item under cursor on the file panel is running otherwise the command line typed in the text field under the panels is running.
The macro runs these commands adding the "-new_console" in the command line. The feature is working if ConEmu has been setup to intercept command line commands (you may check it in the settings, by default it is).

вторник, 21 мая 2013 г.

iNEXT IPTV

Меня продолжительное время донимала проблема доступа к системному диску моего мультимедийного устройства iNEXT 3D Kid с целью размещения на нём плейлиста IPTV моего интернет-провайдера Maximum.NET. Доступом через самба-сервер я когда-то смог разместить его там один раз. Потом сетевой диск исчез, я обновил прошивку до 9980 и один раз опять смог положить но после обновления он опять пропал и никакие мои эксперименты к успеху не приводили пока я, наконец, не обратился в поддержку.
Спасибо огромное Олегу Омельченко, который откликнутся и не только объяснил мне проблемы а также добавил поддержку IPTV моего провайдера в устройство с доступом через IPTV в главном меню. На мой вопрос почему этой информации нет на официальном сайте, Олег ответил, что программное обеспечение в стадии разработки, там всё меняется, поэтому промежуточные решения не выкладываются. Но я всё-таки решил поделиться этой информацией с вами.
Итак, проблемы и их решения:
  • Сетевой диск iNEXT не доступен через включенный самба-сервер. Решается подсоединением любого устройства памяти (диск или флешка) в USB коннектор, что позволяет включить самба-сервер, после чего вы сможете попасть в пункт назначения. Или просто используйте FTP как описано ниже.
  • При заходе через FTP вы попадаете в пустой пользовательский каталог вместо корневой структуры. Решается использованием рутового юзера root без пароля. Используйте именно эти аутентификационные данные вместо тех, которые у вас настроены в устройстве, что бы попасть в коренной каталог системного диска.
  • Вы не обнаружили поддержку IPTV вашего провайдера. Я лично не жаловался на это, но Олег по собственной инициативе, за что ему огромное спасибо, сделал для меня поддержку провайдера Maximum.NET, да заодно и себе в копилку, как я понимаю, добавил :) Так что, видимо, начиная со следующей прошивки она теперь будет поставляться. Ну а пока суть до дела и новой прошивки ещё нет - вот динамический плейлист, любезно сгенерированный Олегом (который будет вживую подкачиваться с сайта Maximum.NET), который надо разместить в системной папке "/data/other/IPTV" используя, например, вышеописанный доступ через FTP.
Для запуска просмотра IPTV, добавленного, как описано в последнем пункте:
  1. Запустить IPTV из приложений.
  2. Нажать ОK чтобы увидеть список каналов для плейлиста который запустился (это не обязательно будет нужный), не обращая внимания на возможные ошибки, возникающие при попытке использования плей-листа по-умолчанию.
  3. Нажимаем кнопку перемотки >> она над зеленой кнопкой и попадаем в список плейлистов (наборы).
  4. Кнопками LEFT и RIGHT листаем страницы в списке плейлистов. Для приаттаченного плейлиста выше будет не на первой странице и называется он Maximum.NET.list
  5. Выбираем нужный Вам плейлист и нажимаем OK, потом выбираем нужный Вам канал и нажимаем OK.
  6. Наслаждаемся просмотром.

пятница, 8 марта 2013 г.

Event Waiter

Needed a possibility to notify a thread about event occurred in anothre thread. Originally other attemps were made to organize the necessary approach inside that threads but then idea came up to use a separate object for this kind of synchronization and it finally came out as pretty intelegent light easy to read approach so good that I wanted to share it with you.

/**
 * Event Waiter object is to synchronize one or several threads with a thread-event originator</br>
 * Thread safe.</br>
 * Actors: event originator thread and one or more event waiter thread(s)</br>
 * Event Waiter thread(s) must call {@link #waitForEvent()} to wait for the Event to occur</br>
 * Event Originator thread must call {@link #eventOccurred()} to notify that the Event has been occurred</br>
 * If the Event has been occurred waiter thread(s) are not blocked on {@link #waitForEvent()} call</br>
 * If the Event has not been occurred yet waiter thread(s) are blocked on {@link #waitForEvent()} call until the Event has occurred</br>
 
 @author vtkachenko
 *
 */
public class EventWaiter {

  private boolean eventOccurred = false;

  /**
   * Once the event has been occurred this method should be called to notify that
   */
  public synchronized void eventOccurred() {
    eventOccurred = true;
    notifyAll();
  }

  /**
   * Method to wait for the event to occur
   @throws InterruptedException
   */
  public synchronized void waitForEvent() throws InterruptedException {
    if (!eventOccurred) {
      wait();
    }
  }
}

And usage example.

public class EventWaiterTest {
  
  private static void waitedFirstTest() {
    
    System.out.println("waitedFirstTest begin");
    
    final EventWaiter eventWaiter = new EventWaiter();
    
    Thread threadWithEvent = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(1000);
        catch (InterruptedException e) {
          e.printStackTrace();
        }

        System.out.println("occurring the event...");
        eventWaiter.eventOccurred();
      }
    });
    threadWithEvent.start();
    
    try {
      System.out.println("waiting for the event...");
      eventWaiter.waitForEvent();
      System.out.println("event occurred");
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    
    System.out.println("waitedFirstTest end");
  }
  
  private static void waitedLastTest() {
    
    System.out.println("waitedLastTest begin");
    
    final EventWaiter eventWaiter = new EventWaiter();
    
    Thread threadWithEvent = new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("occurring the event...");
        eventWaiter.eventOccurred();
      }
    });
    threadWithEvent.start();

    try {
      Thread.sleep(1000);
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    
    try {
      System.out.println("waiting for the event...");
      eventWaiter.waitForEvent();
      System.out.println("event occurred");
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    
    System.out.println("waitedLastTest end");
  }

  /**
   @param args
   */
  public static void main(String[] args) {
    waitedFirstTest();
    waitedLastTest();
  }

}


Java HTML generated using Java2html

понедельник, 16 июля 2012 г.

Simple value assignment in BPEL

I've spent a lot of time on a problem when we need to assign just simple value to the tag body which has some attributes already assigned before. E.g. we have some variable varOut which contains the following structure:

<complexStructure>
  <complexValue someAttr="someAttrValue"></complexValue>
</complexStructure>

To assign some value from the variable varWithSimpleValue to the complexValue tag body now we might want to make a following copy procedure:

<assign name="someName">
  <copy>
    <from variable="varWithSimpleValue"/>
    <to variable="varOut" query="/complexStructure/complexValue"/>
  </copy>
</assign>

But BPEL treats source anyway as a complex structure regardles which type is used to define it, let it be even xsd:string and as a result of this operation the whole complex destination (complexValue with its children which are its attributes for the given example) is replaced thus someAttr will be lost. To solve the problem we can use string function which converts object to simple value and have a copy made like this:

<assign name="someName">
  <copy>
    <from expression="string(bpws:getVariableData(varWithSimpleValue))"/>
    <to variable="varOut" query="/complexStructure/complexValue"/>
  </copy>
</assign>

And better and more logical solution is to use text function for the destination to specify that we are selecting complexValue's simple text content not the whole structure:

<assign name="someName">
  <copy>
    <from variable="varWithSimpleValue"/>
    <to variable="varOut" query="/complexStructure/complexValue/text()"/>
  </copy>
</assign>

Originally the problem appeared with JBPM 3.2 but I believe other BPEL implementation should behave similarly.

вторник, 21 февраля 2012 г.

Our company Serena is IT Innovator of the year!

Yahoo!!!

The company I'm currently working in, Serena Software, is the Pink Elephant 2011 Innovator of the Year!!!
Here is our baby :)

Another news about that on PR-Web

пятница, 13 января 2012 г.

Deadline

Dedicated to IT... What does deadline mean for us :)

воскресенье, 4 декабря 2011 г.

9 simple rules to behave in IT team

Really really great rules to behave properly in IT team! Thanks to the "9 Things That Motivate Employees More Than Money" article by Ilya Posin. Checked on practice :) Do you also believe we should read and follow? ;)
Особенно полезна тем, кто работает в связке с зарубежной командой, что бы учесть бо́льшую мягкость менталитета наших зарубежных коллег. К сожалению, в связи с большей грубостью нашего, я сам иногда ошибаюсь. Надо контролировать себя.

среда, 2 ноября 2011 г.

2011-11-02

Today is very interesting date.
2nd of November, 2011 in ISO 8601 format (YYYY-MM-DD) is 2011-11-02 and (YYYYMMDD) - 20111102 that has symmetrical numbers along (palindrome).

My congratulations to worldwide IT crowd with this significant date! :)

понедельник, 31 октября 2011 г.

Java developers band

Just couldn't resist sharing what I've found with esteemed IT crowd :)