Saturday, April 30, 2011

Why SerialEvent.RI doesn't work?

Hi, I have two computers running this code:

import java.io.; import java.util.; import gnu.io.*;

public class Deb implements SerialPortEventListener, Runnable{

public static final int TIMEOUTSECONDS = 30;
public static final int BAUD = 9600;

static String telefono;
static Boolean llamar = false;

CommPortIdentifier cpiModem = null;
SerialPort modem;

BufferedReader is;
PrintStream os;

Thread hiloMarcado;

int nConnects = 0;

boolean flag = false;
String line;

public static void main(String argv[]) throws PortInUseException, UnsupportedCommOperationException, IOException, InterruptedException, TooManyListenersException {

 if (argv.length>0) {
  telefono = argv[0];
  llamar = true;
 }
 new Deb();  
}

public Deb() throws PortInUseException, UnsupportedCommOperationException, IOException, InterruptedException, TooManyListenersException{  

 Enumeration pList = CommPortIdentifier.getPortIdentifiers();
 while (pList.hasMoreElements()) {

  CommPortIdentifier cpi = (CommPortIdentifier)pList.nextElement();

  if (cpi.getPortType()==CommPortIdentifier.PORT_SERIAL) {

   SerialPort puertoSerie = (SerialPort) cpi.open("DEB", TIMEOUTSECONDS * 1000);
   puertoSerie.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
   puertoSerie.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN & SerialPort.FLOWCONTROL_RTSCTS_OUT);

   BufferedReader is = new BufferedReader(new InputStreamReader(puertoSerie.getInputStream()));
   PrintStream os = new PrintStream(puertoSerie.getOutputStream(), true);

   os.println("AT");
   Thread.sleep(TIMEOUTSECONDS * 50);
   if (!is.ready()) {
    System.out.println("No hay un modem en " + cpi.getName());
   } else {
    System.out.println("Hay un modem en " + cpi.getName());
    cpiModem = cpi;
   }   
   puertoSerie.close();
  }   
 }

 modem = (SerialPort) cpiModem.open("DEBita", TIMEOUTSECONDS * 1000);
 modem.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
 modem.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN & SerialPort.FLOWCONTROL_RTSCTS_OUT);

 is = new BufferedReader(new InputStreamReader(modem.getInputStream()));
 os = new PrintStream(modem.getOutputStream(), true);  

 modem.addEventListener(this);

 modem.notifyOnDataAvailable(true);
 modem.notifyOnCarrierDetect(true);
 modem.notifyOnBreakInterrupt(true);
 modem.notifyOnCTS(true);
 modem.notifyOnDSR(true);
 modem.notifyOnFramingError(true);
 modem.notifyOnOutputEmpty(true);
 modem.notifyOnOverrunError(true);
 modem.notifyOnParityError(true);
 modem.notifyOnRingIndicator(true);

 /*System.out.println(is.read());*/ 

 if (llamar) {   
  hiloMarcado = new Thread(this);
  hiloMarcado.start();
 }

}

public void serialEvent(SerialPortEvent event) {
 switch (event.getEventType()) {
 case SerialPortEvent.OE:
 case SerialPortEvent.FE:
 case SerialPortEvent.PE:
 case SerialPortEvent.DSR:
  System.out.println("Data Set Ready.");
  break;
 case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
  System.out.println("Ignored event");
  break;

 case SerialPortEvent.BI:
  System.out.println("Break Interrupt");
  break;

 case SerialPortEvent.CTS:
  System.out.println("Clear to send");
  break;

 case SerialPortEvent.RI:
  System.out.println("Pick up the receiver.");
  if( event.getNewValue() ) 
  {
   System.out.println("Ring Indicator On");
  }
  else 
  {
   System.out.println("Ring Indicator Off");
  }
  break;


 case SerialPortEvent.CD:
  if (event.getNewValue()) {
   System.out.println("Connected");
   nConnects = nConnects + 1;   
  } else {
   System.out.println("Disconnected");
  }
  break;

 case SerialPortEvent.DATA_AVAILABLE: 
  handleData();
  break;
 }
}


public void run() {
 while (true) {
  if (nConnects == 0) {
   try {
    if (!modem.isCD()) {      
     System.err.println("Estamos llamando  ...");
     os.println("ATDT" + telefono);
    }
    Thread.sleep(TIMEOUTSECONDS * 2000);

   } catch (Exception ex) {
    System.err.println("Failed to write message");
   }
  }
 }
}

public void handleData() {
 try {
  int avail = modem.getInputStream().available();
  byte[] response = new byte[avail];
  StringBuffer strbuf = new StringBuffer();
  modem.getInputStream().read(response, 0, avail);


   if (!flag) {
    modem.getInputStream().read(response, 0, avail);
    for (int i = 0; i < avail; i++) {
     Thread.sleep(5);
     os.write((char) response[i]);
     System.out.print((char) response[i]);
    }
   }
 } catch (IOException ie1) {
  System.out.println("File " + ie1);
 } catch (InterruptedException in) {
  System.out.println("Interrupt " + in);
 }

}

}

It isn't the final version, I'm only seeing how it works. The thing is that when I use this code to dial to a phone number, for example, my mobile phone, it works, but it doesn't work the other way round; that is, calling from my number and acting the programme as a listener. I tried also with 2 computers, neither of them get the calls from the other end. Am I doing something wrong? I would appreciate any help.

From stackoverflow
  • I already detected the problem, it is the modem. It's an old modem I have to use while the new ones don't arrive. I tried the laptop modem on the same telephone line and everything works correctly, it detects the RI event. I suppose there is something wrong in the configuration of the modem... but I'm not sure, because it works well when receiving a fax, or when other computers phones this one using hyperterminal or simmilar programs... Does anyone know any at command that I could use to get my modem to detect RI events? Or is any other thing the problem?

    Thanks

  • AT-compatible modems should send a “RING” over the data line to notify you of an incoming ring event. Maybe you could listen for that?

Using a function in a filter query in Solr

I want to filter my result set before I search. I know the correct way to do this is by using the filter query (fq) parameter. However, I want to filter based on the output of a function performed on a field.

I have a field 'rating' which is an integer in the range of 1 to ~75000. The upper limit may change. I want to filter to the top 500 items with the highest 'rating'. In SQL this would be something like:

... ORDER BY rating DESC LIMIT 500

I think I can get the documents in solr ranked by rating descending by using the function rord(rating), so basically I would like to do:

fq=rord(rating):[0 TO 500]

But that does not seem possible. Does anyone know what else I could do?

From stackoverflow
  • Unless I'm missing something, you could not sort by the rating field and then simply take the first 500. That would be identical to your SQL example.

    cubabit : I can't limit the responses to 500 because a. That would take away the point of paging; and b. I want to run a filter query so I can facet inside the 500 documents.
  • Cross-posted in the solr-user mailing list, answered by Yonik.

  • Thanks to Yonik Seeley on the Solr mailing list:

    Solr 1.4 can now do range queries on arbitrary functions: http://lucene.apache.org/solr/api/org/apache/solr/search/FunctionRangeQParserPlugin.html

    Note that ord() and rord() won't work properly in Solr 1.4 trunk. Lucene has changed to searching per-segment in a MultiReader and hence you will currently get the ord() or rord() in that segment, not in the whole index.

  • So what is the solution for this? to filter to 500 results?

    cubabit : I think the answer is to use the FunctionRangeQParserPlugin at http://lucene.apache.org/solr/api/org/apache/solr/search/FunctionRangeQParserPlugin.html but I had to do it via creating a new field holding the sort rank for my data as we use Solr 1.3.

Get current system setting's fraction separator

In my app I parse a value from xml (string) to a double. The value in the xml happens to have the dot as a fraction seperator whereas the system takes the current system settings and can have a different separator (dev system takes the comma for example).

Is there a way to tell double.TryParse() the dot is the fraction separator?
Should I manually replace the dot with the system's fraction separator? If so, how do I get this?

From stackoverflow
  • Pass CultureInfo.InvariantCulture into double.TryParse:

    double value;
    bool success = double.TryParse(text, NumberStyles.Float,
                                   CultureInfo.InvariantCulture,
                                   out value);
    

    (For genuinely standard XML formatting, Frederik's suggestion of using XmlConvert is the best idea though.)

  • What you should do, in this situation, is use the XmlConvert class and its members to convert the value like it exists in the XML file to a regular variable. :)

    borisCallens : I didn't know such a thing existed. And why exactly is this class better then double.trypars()? I understand it can come in handy when there are special characters involved. But there is no tryparse as far as I can see.

Using Autonumbering in Access - INSERT statements

I'm having trouble running an INSERT statement where there's an autonumber as the PK field. I have an Auto-incrementing long as the Primary Key, and then 4 fields of type double; and yet Access (using ADO) seems to want five values for the insert statement.

INSERT INTO [MY_TABLE] VALUES (1.0, 2.0, 3.0, 4.0);
>> Error: Number of query values and destinations fields are not the same.

INSERT INTO [MY_TABLE] VALUE (1, 1.0, 2.0, 3.0, 4.0);
>> Success!!

How do I use Autonumbering to actually autonumber?

From stackoverflow
  • If you do not want to provide values for all columns that exists in your table, you've to specify the columns that you want to insert. (Which is logical, otherwise how should access, or any other DB, know for which columns you're providing a value)?

    So, what you have to do is this:

    INSERT INTO MyTable ( Column2, Column3, Column4) VALUES ( 1, 2, 3 )
    

    Also , be sure that you omit the Primary Key column (which is the autonumber field). Then, Access will set it to the next value by itself.

    You can then retrieve the primary-key value of the newly inserted record by executing a

    SELECT @@identity FROM MyTable
    

    statement.

    Smashery : Thank you so much! You not only answered my question, but you answered the next question I was in the process of writing: how to extract the autonumber after the insert. Cheers!
  • Mention the column names in your query as you are providing only 4 values whereas you have 5 columns in that table. Database need to know the value you providing is for which column.

  • My understanding though is that if you are using SQL Server or similar and there are triggers which add additional records the @@IDENTITY may be that of the other additional records.